layui.extend({
    'fzyParser':'fzyEditor/fzyParser'
}).define(['fzyParser'],function (exports) {
    'use strict';
    const $=layui.jquery
        ,form = layui.form
        ,layer = layui.layer
        ,MOD_NAME='fzyEditor'
        ,COMMON_PATH = layui.cache.base+'fzyEditor/'
        ,version = 'v2.0.1'
        ,util = layui.util
        ,fzyParser = layui.fzyParser
        ,upload = layui.upload

    //检查运行环境
    if(window.location.href.indexOf('file://')>-1){
        return $('body').html('<div style="user-select:none;position: fixed;width: 300px;height: 100px;line-height: 100px;left: calc(50% - 150px);top:calc(50% - 50px);text-align: center;border-radius: 5px;border: 1px dotted #666">请在服务环境下运行本项目</div>'),
            layer.msg('请在服务环境运行');
    }
    $.getScript(COMMON_PATH+'js/APlayer.min.js');//提前载入APlayer,否则音乐播放器不生效
    /**
     * 加入编辑器样式表
     */
    layui.link(COMMON_PATH+'css/fzyEditor.css');
    /**
     * toolbar
     */
    const toolbar = {
        undo:`<div class="-fzy-tool-item" editor-title="撤销" editor-event="undo"><i class="iconfont icon-chexiaozuo"></i></div>`,
        redo:`<div class="-fzy-tool-item" editor-title="重做" editor-event="redo"><i class="iconfont icon-chexiaoyou"></i></div>`,
        "|":`<div class="-fzy-tool-item divider">|</div>`,
        bold:`<div class="-fzy-tool-item" editor-title="加粗" editor-event="bold"><i class="iconfont icon-zitijiacu"></i></div>`,
        italic:`<div class="-fzy-tool-item" editor-title="斜体" editor-event="italic"><i class="iconfont icon-italic"></i></div>`,
        underline:`<div class="-fzy-tool-item" editor-title="下划线" editor-event="underline"><i class="iconfont icon-zitixiahuaxian"></i></div>`,
        del:`<div class="-fzy-tool-item" editor-title="删除线" editor-event="del"><i class="iconfont icon-strikethrough"></i></div>`,
        left:`<div class="-fzy-tool-item" editor-title="左对齐" editor-event="left"><i class="iconfont icon-juzuo"></i></div>`,
        right:`<div class="-fzy-tool-item" editor-title="右对齐" editor-event="right"><i class="iconfont icon-juyou"></i></div>`,
        center:`<div class="-fzy-tool-item" editor-title="居中" editor-event="center"><i class="iconfont icon-juzhong1"></i></div>`,
        unorderedList:`<div class="-fzy-tool-item" editor-title="无序列表" editor-event="unorderedList"><i class="iconfont icon-unorderedList"></i></div>`,
        orderedList:`<div class="-fzy-tool-item" editor-title="有序列表" editor-event="orderedList"><i class="iconfont icon-youxuliebiao"></i></div>`,
        tl:`<div class="-fzy-tool-item" editor-title="任务-未完成" editor-event="tl"><i class="iconfont icon-fuxuankuang" style="font-size: 20px"></i></div>`,
        tlx:`<div class="-fzy-tool-item" editor-title="任务-完成" editor-event="tlx"><i class="pi pi-check-square" style="font-size: 15px"></i></div>`,
        h1:`<div class="-fzy-tool-item" editor-title="标题1" editor-event="h1"><i class="iconfont icon-h1"></i></div>`,
        h2:`<div class="-fzy-tool-item" editor-title="标题2" editor-event="h2"><i class="iconfont icon-h2"></i></div>`,
        h3:`<div class="-fzy-tool-item" editor-title="标题3" editor-event="h3"><i class="iconfont icon-h3"></i></div>`,
        h4:`<div class="-fzy-tool-item" editor-title="标题4" editor-event="h4"><i class="iconfont icon-h4"></i></div>`,
        h5:`<div class="-fzy-tool-item" editor-title="标题5" editor-event="h5"><i class="iconfont icon-h5"></i></div>`,
        h6:`<div class="-fzy-tool-item" editor-title="标题6" editor-event="h6"><i class="iconfont icon-h"></i></div>`,
        centerTitle:`<div class="-fzy-tool-item" editor-title="居中标题" editor-event="centerTitle"><i class="iconfont icon-juzhong"></i></div>`,
        link:`<div class="-fzy-tool-item" editor-title="超链接" editor-event="link"><i class="iconfont icon-chaolianjie"></i></div>`,
        hr:`<div class="-fzy-tool-item" editor-title="横线" editor-event="hr"><i class="iconfont icon-hengxian"></i></div>`,
        codeBlock:`<div class="-fzy-tool-item" editor-title="代码块" editor-event="codeBlock"><i class="iconfont icon-daimakuai"></i></div>`,
        inlineCode:`<div class="-fzy-tool-item" editor-title="行内代码" editor-event="inlineCode"><i class="iconfont icon-hangneidaima"></i></div>`,
        html5:`<div class="-fzy-tool-item" editor-title="HTML代码" editor-event="html5"><i class="iconfont icon-HTML-fill"></i></div>`,
        table:`<div class="-fzy-tool-item" editor-title="表格" editor-event="table"><i class="iconfont icon-biaoge"></i></div>`,
        quote:`<div class="-fzy-tool-item" editor-title="引用" editor-event="quote"><i class="iconfont icon-quote"></i></div>`,
        toc:`<div class="-fzy-tool-item" editor-title="设置目录" editor-event="toc"><i class="iconfont icon-daohang2"></i></div>`,
        img:`<div class="-fzy-tool-item" editor-title="图片" editor-event="img"><i class="pi pi-image"></i></div>`,
        face:`<div class="-fzy-tool-item" editor-title="表情" editor-event="face"><i class="iconfont icon-kulian"></i></div>`,
        symbol:`<div class="-fzy-tool-item" editor-title="符号" editor-event="symbol"><i class="iconfont icon-copyright"></i></div>`,
        smile:`<div class="-fzy-tool-item" editor-title="符号表情" editor-event="smile"><i class="iconfont icon-fuhaobiaoqing "></i></div>`,
        images:`<div class="-fzy-tool-item" editor-title="多图" editor-event="images"><i class="pi pi-images"></i></div>`,
        video:`<div class="-fzy-tool-item" editor-title="MP4/M3U8视频" editor-event="video"><i class="iconfont icon-file-mp4" style="font-size: 16px;"></i></div>`,
        bili:`<div class="-fzy-tool-item" editor-title="哔哩哔哩视频" editor-event="bili"><i class="iconfont icon-bilibili"></i></div>`,
        audio:`<div class="-fzy-tool-item" editor-title="音频" editor-event="audio"><i class="iconfont icon-yinle"></i></div>`,
        file:`<div class="-fzy-tool-item" editor-title="插入附件" editor-event="file"><i class="iconfont icon-fujian-wenjian"></i></div>`,
        datetime:`<div class="-fzy-tool-item" editor-title="日期时间" editor-event="datetime"><i class="pi pi-clock"></i></div>`,
        indent:`<div class="-fzy-tool-item" editor-title="缩进" editor-event="indent"><i class="iconfont icon-a-00-4yousuojincaidan"></i></div>`,
        btn:`<div class="-fzy-tool-item" editor-title="多彩按钮" editor-event="btn"><i class="iconfont icon-button" style="font-size: 20px;"></i></div>`,
        noteBtn:`<div class="-fzy-tool-item" editor-title="便条按钮" editor-event="noteBtn"><i class="iconfont icon-anniu" style="font-size: 25px;"></i></div>`,
        dashedLine:`<div class="-fzy-tool-item" editor-title="彩色虚线" editor-event="dashedLine"><i class="iconfont icon-xuxian1" style="font-size: 25px;"></i></div>`,
        hidden:`<div class="-fzy-tool-item" editor-title="回复可见" editor-event="hidden"><i class="iconfont icon-bukejian1"></i></div>`,
        marquee:`<div class="-fzy-tool-item" editor-title="跑马灯" editor-event="marquee"><i class="iconfont icon-paomadeng"></i></div>`,
        progressBar:`<div class="-fzy-tool-item" editor-title="进度条" editor-event="progressBar"><i class="iconfont icon-jindutiao" style="font-size: 24px;"></i></div>`,
        card:`<div class="-fzy-tool-item" editor-title="默认卡片" editor-event="card"><i class="iconfont icon-kapian"></i></div>`,
        cardList:`<div class="-fzy-tool-item" editor-title="卡片列表" editor-event="cardList"><i class="iconfont icon-card-list"></i></div>`,
        tabPage:`<div class="-fzy-tool-item" editor-title="选项卡片" editor-event="tabPage"><i class="iconfont icon-xuanxiangka" style="font-size: 22px;"></i></div>`,
        foldCard:`<div class="-fzy-tool-item" editor-title="折叠卡片" editor-event="foldCard"><i class="iconfont icon-zhediemianban" style="font-size: 16px;"></i></div>`,
        labelCard:`<div class="-fzy-tool-item" editor-title="标注卡片" editor-event="labelCard"><i class="pi pi-bookmark-fill" style="font-size: 15px;"></i></div>`,
        fieldCard:`<div class="-fzy-tool-item" editor-title="描述卡片" editor-event="fieldCard"><i class="iconfont icon-FieldSet"></i></div>`,
        timeAxis:`<div class="-fzy-tool-item" editor-title="时间轴" editor-event="timeAxis"><i class="iconfont icon-shijianzhou" style="font-size: 20px;"></i></div>`,
        banner:`<div class="-fzy-tool-item" editor-title="轮播" editor-event="banner"><i class="iconfont icon-lunbotu_fuzhi"></i></div>`,
        grid:`<div class="-fzy-tool-item" editor-title="宫格" editor-event="grid"><i class="iconfont icon-split-screen-compare" style="font-size: 15px;"></i></div>`,
        copy:`<div class="-fzy-tool-item" editor-title="复制" editor-event="copy"><i class="iconfont icon-fuzhi" style="font-size: 17px;"></i></div>`,
        note:`<div class="-fzy-tool-item" editor-title="提示" editor-event="note"><i class="iconfont icon-tishi" style="font-size: 20px;"></i></div>`,
        cloudPan:`<div class="-fzy-tool-item" editor-title="云盘" editor-event="cloudPan"><i class="iconfont icon-yunpan" style="font-size: 15px;"></i></div>`,
        clear:`<div class="-fzy-tool-item" editor-title="清屏" editor-event="clear"><i class="iconfont icon-empty"></i></div>`,
        preview:`<div class="-fzy-tool-item" editor-title="预览" editor-event="preview"><i class="iconfont icon-zitiyulan"></i></div>`,
        fullscreen:`<div class="-fzy-tool-item" editor-title="全屏" editor-event="fullscreen"><i class="iconfont icon-quanping1"></i></div>`,
        help:`<div class="-fzy-tool-item" editor-title="帮助" editor-event="help"><i class="iconfont icon-bangzhu"></i></div>`,
        gotoLine:`<div class="-fzy-tool-item" editor-title="跳转到行" editor-event="gotoLine"><i class="iconfont icon-tiaozhuanzhida"></i></div>`,
        search:`<div class="-fzy-tool-item" editor-title="搜索" editor-event="search"><i class="iconfont icon-sousuo"></i></div>`,
        about:`<div class="-fzy-tool-item" editor-title="关于" editor-event="about"><i class="iconfont icon-guanyuwomen" style="font-size: 18px;font-weight: 600"></i></div>`,
        ucfirst:`<div class="-fzy-tool-item" editor-title="首字母大写" editor-event="ucfirst"><i class="iconfont icon-zitidaxiao" style="font-size: 20px;"></i></div>`,
        uppercase:`<div class="-fzy-tool-item" editor-title="转大写字母" editor-event="uppercase"><i class="iconfont icon-dahaoziti"></i></div>`,
        lowercase:`<div class="-fzy-tool-item" editor-title="转小写字母" editor-event="lowercase"><i class="iconfont icon-a" style="font-size: 13px;"></i></div>`,
        pageBreak:`<div class="-fzy-tool-item" editor-title="分页符" editor-event="pageBreak"><i class="iconfont icon-fenyefu" style="font-size: 15px;"></i></div>`,
    };
    /**
     * 编辑器JS代码
     * @constructor
     */
    const MD = function (id,options){
        let _this = this,ED=undefined,EL = {},Parser = new fzyParser();
        _this.classPrefix = "-fzy-editor-";
        _this.dialogZindex = 99999;
        _this.isIE = (window.navigator.appName == "Microsoft Internet Explorer");
        _this.isIE8 = (_this.isIE && navigator.appVersion.match(/8./i) == "8.");
        _this.pluginPath = COMMON_PATH+'plugins/';
        _this.face = {
            faceRes:{},
            faceArr:[]
        };

        _this.keyMaps = {
            "Ctrl-1"       : "h1",
            "Ctrl-N0"      : "h1",
            "Ctrl-2"       : "h2",
            "Ctrl-N2"      : "h2",
            "Ctrl-3"       : "h3",
            "Ctrl-N3"      : "h3",
            "Ctrl-4"       : "h4",
            "Ctrl-N4"      : "h4",
            "Ctrl-5"       : "h5",
            "Ctrl-N5"      : "h5",
            "Ctrl-6"       : "h6",
            "Ctrl-N6"      : "h6",
            // "Ctrl-A"       : "",//全选
            "Ctrl-Shift-A" : "about",
            "Ctrl-B"       : "bold",
            // "Ctrl-C"       : "",//复制,可自定义覆盖
            "Ctrl-D"       : function (){
                let cm = _this.Ed;
                let cursor = cm.getPosition();//获取当前位置
                let lineTex   = cm.getModel().getLineContent(cursor.lineNumber);//获取当前行内容
                if(lineTex) {
                    cm.setPosition(new monaco.Position(cursor.lineNumber, lineTex.length + 1));//光标跳转到当前行最后
                    let selection = cm.getSelection();//获取当前选中位置
                    _this.replaceSelection(selection, '\n' + lineTex);//粘贴并跳转到下一行
                }
                cm.focus();

            },//复制上一行
            "Ctrl-T"       : "datetime",//绑定时间
            "Ctrl-F"       : "search",
            "Ctrl-E"       : 'face',//绑定表情
            "Ctrl-Alt-E"   : 'smile',//绑定smile表情
            "Ctrl-N"       : "symbol",//绑定字符
            "Ctrl-G"       : "gotoLine",//跳转到行
            "Ctrl-H"       : "hr",//横线
            "Ctrl-Shift-H" : "html5",//html5代码
            "Ctrl-I"       : "italic",//斜体
            "Ctrl-K"       : "inlineCode",//行内代码
            "Ctrl-J"       : "codeBlock",//代码块
            "Ctrl-R"       : "replace",
            "Ctrl-Alt-R"   : "replaceAll",
            "Ctrl-O"       : "unorderedList",//无序列表
            "Ctrl-L"       : "link",//链接
            "Ctrl-U"       : "orderedList",//有序列表
            "Ctrl-M"       : "img",//单图上传
            "Ctrl-Alt-M"   : "images",//多图上传
            // "Ctrl-P"       : "",//打印,可自定义覆盖
            // "Ctrl-S"       : "",//存储页面，可自定义覆盖
            // "Ctrl-V"       : "",//粘贴，可自定义覆盖
            "Shift-A"      : function() {
                let cm        = _this.Ed;
                let selection = cm.getSelection();
                let cursor = cm.getPosition();
                let selectionText = _this.getSelectionText(selection)
                _this.replaceSelection(selection,"@" + selectionText);
                if (selection === "") {
                    cm.setPosition(new monaco.Position(cursor.lineNumber, 2));
                }
            },//@
            "Ctrl-Q"       : "quote",//引用
            "Shift-Ctrl-S" : "del", //删除线
            "Shift-Ctrl-K" : "tex",  // KaTeX，未定义科学公式，需要自定义
            "Ctrl-W"       : "clear",//清除

            "Ctrl-Alt-H"   : "help", //帮助
            "Ctrl-Shift-U" : "ucfirst",//首字母大写
            "Ctrl-Alt-U"   : "uppercase",//全部转大写
            "Shift-Alt-U"  : "lowercase",//全部转小写
            "Shift-T"      : "table",//载入表格
            "Shift-Alt-P"  : "pageBreak",//分页符
            // "F9"           : "watch",//未知
            "F10"          : "preview",//预览
            "F11"          : "fullscreen",//编辑器全屏
            "Enter"        : function (){
                let cm        = _this.Ed;
                let cursor    = cm.getPosition();
                let selection = cm.getSelection();
                let selectionText = _this.getSelectionText(selection);//获取选中内容
                let lineTex   = cm.getModel().getLineContent(cursor.lineNumber);//获取当前行内容
                if(!selectionText) {
                    let match = /^( *)((?:(?:\d+\.)|(?:-(?: \{ x \})?)) )?(.*)/.exec(lineTex);
                    if (match[2]) {
                        if (match[3] === '') {
                            let currentLineNumber = cursor.lineNumber; //当前行号
                            //选中当前行的内容
                            const lineStart = new monaco.Position(currentLineNumber, 1);//实例化行开始位置
                            const lineEnd = new monaco.Position(currentLineNumber, cm.getModel().getLineMaxColumn(currentLineNumber));//实例化行结束位置
                            cm.setSelection(new monaco.Range(lineStart.lineNumber, lineStart.column, lineEnd.lineNumber, lineEnd.column)); //选中行内容
                            selection = cm.getSelection();//重新获取选中区域坐标
                            _this.replaceSelection(selection,'');
                        } else if (match[2].length === 3) {
                            let m = /^(\d+)\. /.exec(match[2]);
                            _this.replaceSelection(selection,match[1] +'\n'+match[1] + (parseInt(m[1]) + 1) + '. ');
                        } else {
                            _this.replaceSelection(selection,match[1] +'\n'+ match[1] + match[2]);
                        }
                    } else {
                        _this.replaceSelection(selection,'\n');
                    }
                }else{
                    _this.replaceSelection(selection,'\n');
                }
                cm.revealLine(cursor.lineNumber+1,'Smooth');
            },//回车事件
        };

        _this.setting = {
            tools:[
                'undo','redo',
                '|',
                'bold', 'italic', 'underline', 'del','indent',
                '|',
                'ucfirst','uppercase','lowercase',
                '|',
                /*'left', 'center', 'right',*/'orderedList', 'unorderedList', 'tl','tlx',
                '|',
                'h1', 'h2', 'h3', 'h4', 'h5', 'h6','centerTitle',
                '|',
                'hr', 'dashedLine','link', 'codeBlock','inlineCode','html5',
                '|',
                'table', 'quote', /*'toc',*/'symbol','smile','face', 'img','images','file','video','audio','bili','datetime','pageBreak',
                '|',
                'btn','noteBtn','hidden','progressBar','marquee','card','tabPage','cardList','foldCard','labelCard','fieldCard','timeAxis','banner','grid','copy','note','cloudPan',
                '|',
                'gotoLine','search','clear','fullscreen', 'preview','help','about'],
            toolbarModes:{
                full:[
                    'undo','redo',
                    '|',
                    'bold', 'italic', 'underline', 'del','indent',
                    '|',
                    'ucfirst','uppercase','lowercase',
                    '|',
                    /*'left', 'center', 'right',*/'orderedList', 'unorderedList', 'tl','tlx',
                    '|',
                    'h1', 'h2', 'h3', 'h4', 'h5', 'h6','centerTitle',
                    '|',
                    'hr', 'dashedLine','link', 'codeBlock','inlineCode','html5',
                    '|',
                    'table', 'quote', /*'toc',*/'symbol','smile','face', 'img','images','file','video','audio','bili','datetime','pageBreak',
                    '|',
                    'btn','noteBtn','hidden','progressBar','marquee','card','tabPage','cardList','foldCard','labelCard','fieldCard','timeAxis','banner','grid','copy','note','cloudPan',
                    '|',
                    'gotoLine','search','clear','fullscreen', 'preview','help','about'
                ],
                simple:[
                    'undo','redo',
                    '|',
                    'bold', 'italic', 'underline', 'del','indent',
                    '|',
                    'h1', 'h2', 'h3', 'h4', 'h5', 'h6','ucfirst','uppercase','lowercase',
                    '|',
                    'hr','codeBlock','link','face','img','quote','orderedList', 'unorderedList',
                    '|',
                    'clear','preview','help','about'
                ],
                mini:[
                    "undo", "redo", "|",
                    "clear", "preview", "|",
                    "help", "about"
                ]
            },//all,
            autoTool:{},//自定义扩展工具栏{名称:图标}
            autoToolbarHandles:{},//自定义扩展工具栏方法{名称:fn}
            autoParser:function (str){
                return str;
            },
            value: '',
            theme:'vs-dark',
            language: 'markdown',
            local:'zh-cn',//语言
            height:600, //编辑器高度
            enabled:false,
            fontSize: 16,
            preview:true, //是否默认打开预览
            syncScrolling:true,//是否同步滚动
            player:undefined,//m3u8/mp4播放器地址，需要自己配置
            uploadImage:undefined,//图片上传接口或方法,{url,data}或fun
            uploadFile:undefined,//文件上传接口或方法,{url,data}或fun
            uploadVideo:undefined,//视频上传接口或方法,{url,data}或fun
            uploadAudio:undefined,//音频上传接口或方法,{url,data}或fun,所有上传参数遵循layui.upload的参数
            keyMap:{},//自定义快捷键
            change(){},//编辑器内容改变事件
        };

        _this.config = $.extend({},_this.setting,options);

        let toolBars = [];
        let tools = $.extend({},toolbar,_this.config.autoTool);
        if(typeof _this.config.tools === 'string' && ['full','simple','mini'].indexOf(_this.config.tools)!==-1){
            layui.each(_this.config.toolbarModes[_this.config.tools], function (index, item) {
                tools[item] && toolBars.push(tools[item]);
            });
        }else if(Array.isArray(_this.config.tools)){
            layui.each(_this.config.tools, function (index, item) {
                tools[item] && toolBars.push(tools[item]);
            });
        }
        //随机数
        function randomString(length = 10) {
            var result = '';
            var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
            var charactersLength = characters.length;
            for (var i = 0; i < length; i++) {
                result += characters.charAt(Math.floor(Math.random() * charactersLength));
            }
            return result;
        }
        const MDID = randomString(10);
        if(typeof id === 'string' && id.trim()){
            id = id.replace('#','');
            if(_this.isIE){
                return $(`#${id}`).html('编辑器不支持当前浏览器，请更换科学浏览器，如谷歌浏览器、360极速模式、QQ浏览器极速内核、火狐浏览器、Edge浏览器等');
            }
            _this.defaultText = $('#'+id).text();
            let themeClass=_this.config.theme;
            if(_this.config.theme!=='dark'){
                themeClass = 'light';
            }else{
                themeClass = 'dark';
                _this.config.theme = 'vs-dark';
            }
            EL.editor = $('#'+id).addClass('-fzy-editor '+themeClass).html([
                `<div class="-fzy-editor-header -fzy-tool">${toolBars.join('')}</div>`,
                `<div class="-fzy-editor-content ${_this.config.preview?'viewed':''}">`,
                    `<div id="${MDID}" class="-editor-write" style="height: ${_this.config.height}px;"></div>`,
                    `<div class="-fzy-editor-scope" style="height: ${_this.config.height}px;"></div>`,
                    `<div class="-fzy-editor-view" style="height: ${_this.config.height}px;overflow-y:auto;position: relative;">`,
                        `<div class="fzy-view"><div class="fzy-view-tip">预览区</div></div>`,
                    `</div>`,
                `</div>`,
                `<div class="-fzy-editor-mask"></div>`,
                `<div class="-fzy-editor-container-mask"></div>`,
            ].join(''));
            if(_this.config.preview){
                $('.-fzy-tool').find('*[editor-event="preview"]').addClass('active');
            }
            _this.EL = EL;
        }else{
            return layui.hint().error('编辑器ID未设置');
        }

        let t = COMMON_PATH+'monaco-editor/';

        $.getScript(t + "vs/loader.js",function () {
            require.config({
                paths:{
                    vs:t+'vs'
                }
            }),
            require(['vs/editor/editor.main','vs/nls.messages.zh-cn'],_this.initEditor),
            $.getScript(COMMON_PATH+'js/prism.js'),
            $.getScript(COMMON_PATH+'js/fzy.short.js');

        });

        _this.initEditor = function (){
            _this.cm = monaco.editor,
            _this.Ed = ED = _this.cm.create(document.getElementById(MDID),{
                value: _this.config.value || _this.defaultText,
                language: _this.config.language || 'markdown',
                automaticLayout: true,
                scrollBeyondLastLine: !1,
                tabSize: 2,
                minimap: {
                    enabled: _this.config.enabled,
                    autohide: false,
                    showMarkSectionHeaders:true,
                },
                overviewRulerBorder: false,
                theme:_this.config.theme,
                renderLineHighlightOnlyWhenFocus: !0,
                wordWrap: "on",//换行
                local: _this.config.local || 'zh-cn',//默认提示语言中文
                fontSize: _this.config.fontSize || '16',
            }),
            _this.EL.editor.find('div.-fzy-editor-container-mask').remove(),
            _this.mouseOverToolBar();
            _this.resize(),
            _this.scopeMiddle(),
            _this.bindToolBarEvent(),
            _this.listenEvent(),
            _this.bindKeyMapEvent(),
            _this.bindScrollEvent(_this.config.syncScrolling);
        };

        //鼠标悬停工具栏
        _this.mouseOverToolBar = function (){
            let tipIndex=undefined;
            let theme = _this.config.theme!=='light'?'#333':'#666';
            _this.EL.editor.find('.-fzy-tool').on('mouseenter','.-fzy-tool-item',function(){
                let title = $(this).attr('editor-title');
                if(title) {
                    tipIndex = layer.tips(title, this,{
                        tips: [1, theme]
                    });
                }
            }).on('mouseleave','.-fzy-tool-item',function(){
                if(tipIndex){
                    layer.close(tipIndex);
                }
            });
        };
        //编辑器编辑区和预览区拉伸
        _this.scopeMiddle = function (){
            const move = (nowClientX, nowWidth, clientX) => {
                let moveX = nowClientX - clientX;
                let moveWidth = nowWidth + moveX;
                if (moveWidth <= 0) moveWidth = 0;
                if (moveWidth >= $('.-fzy-editor-content').outerWidth() - 16) moveWidth = $('.-fzy-editor-content').outerWidth() - 16;
                $('.-fzy-editor-view').width(moveWidth);
            };
            $('.-fzy-editor-scope').on({
                mousedown: e => {
                    e.preventDefault();
                    e.stopPropagation();
                    const nowWidth = $('.-fzy-editor-view').outerWidth();
                    const nowClientX = e.clientX;
                    $('.-fzy-editor-view').addClass('move');
                    document.onmousemove = _e => {
                        if (window.requestAnimationFrame) requestAnimationFrame(() => move(nowClientX, nowWidth, _e.clientX));
                        else move(nowClientX, nowWidth, _e.clientX);
                    };
                    document.onmouseup = () => {
                        document.onmousemove = null;
                        document.onmouseup = null;
                        $('.-fzy-editor-view').removeClass('move');
                    };
                    return false;
                },
                touchstart: e => {
                    e.preventDefault();
                    e.stopPropagation();
                    const nowWidth = $('.-fzy-editor-view').outerWidth();
                    const nowClientX = e.originalEvent.targetTouches[0].clientX;
                    $('.-fzy-editor-view').addClass('move');
                    document.ontouchmove = _e => {
                        if (window.requestAnimationFrame) requestAnimationFrame(() => move(nowClientX, nowWidth, _e.targetTouches[0].clientX));
                        else move(nowClientX, nowWidth, _e.targetTouches[0].clientX);
                    };
                    document.ontouchend = () => {
                        document.ontouchmove = null;
                        document.ontouchend = null;
                        $('.-fzy-editor-view').removeClass('move');
                    };
                    return false;
                }
            });
        };
        //提示信息
        _this.errorMsg = function (msg){
            msg = msg || '<font color="#cd5c5c">没有写提示信息</font>';
            return layer.msg(msg,{icon:2, anim:6});
        };
        _this.successMsg = function (msg){
            msg = msg || '<font color="#cd5c5c">没有写提示信息</font>';
            return layer.msg(msg,{icon:1, anim:5});
        };
        _this.warningMsg = function (msg){
            msg = msg || '<font color="#cd5c5c">没有写提示信息</font>';
            return layer.msg(msg,{icon:0, anim:6});
        };
        //插入代码
        _this.replaceSelection = function (selection,str){
            let cm = _this.Ed;
            cm.executeEdits('insert-code',[
                {
                    range:selection,
                    text:str
                }
            ]);
            let cursor = cm.getPosition();
            cm.revealLine(cursor.lineNumber,'Smooth');
        };
        //获取选中内容
        _this.getSelectionText = function (selection){
            let cm = _this.Ed;
            let model = cm.getModel(); // 获取编辑器的模型

            return model.getValueInRange(selection);
        }

        //首字母转大写
        _this.firstUpperCase = function(str) {
            return str.toLowerCase().replace(/\b(\w)/, function($1){
                return $1.toUpperCase();
            });
        };
        //字母转大写,废弃
        _this.ucwords = function (str) {
            return str.toLowerCase().replace(/\b(\w)|\s(\w)/g, function($1) {
                return $1.toUpperCase();
            });
        };
        //载入表情json文件
        _this.initFace=function (callback){
            $.get(_this.pluginPath+'face/json/face.json?v='+Math.random(),function (res){
                _this.face.faceRes = res;
                let arr = Object.keys(_this.face.faceRes);
                for(let name of arr){
                    if(name!=='颜文字'){
                        _this.face.faceArr = _this.face.faceArr.concat(_this.face.faceRes[name]);
                    }
                }
                if(typeof callback === 'function'){
                    return callback();
                }
            });
        };
        //提取表情包的文字
        _this.getFaceTitle = (str) => {
            const match = str.match(/[:@$(]\(([^)]+)\)/);
            return match ? match[1] : '';
        };
        //载入特殊字符json文件
        _this.initSymbol=function (callback){
            $.get(_this.pluginPath+'face/json/character.json',function (res){
                if(typeof callback === 'function'){
                    return callback(res);
                }
            });
        };
        //载入符号表情
        _this.initSmile = function (callback){
            $.get(_this.pluginPath+'face/json/emoji.json',function (res){
                if(typeof callback === 'function'){
                    return callback(res);
                }
            });
        }
        //载入日期-时间
        _this.handleTime = function (callback) {
            const time = new Date();
            const _Year = time.getFullYear();
            const _Month = String(time.getMonth() + 1).padStart(2, 0);
            const _Date = String(time.getDate()).padStart(2, 0);
            const _Hours = String(time.getHours()).padStart(2, 0);
            const _Minutes = String(time.getMinutes()).padStart(2, 0);
            const _Seconds = String(time.getSeconds()).padStart(2, 0);
            const _Day = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'][time.getDay()];
            const _time = `${_Year}-${_Month}-${_Date} ${_Hours}:${_Minutes}:${_Seconds} ${_Day}\n`;
            if(typeof callback === 'function'){
                return callback(_time);
            }
            return _time;
        };
        //载入Mtitle
        _this.handleMTitle = function (){
            let cm = _this.Ed;
            let selection = cm.getSelection(); // 获取当前的选择区域
            let selectedText = _this.getSelectionText(selection);

            let mTitleHtml=`<div class="fitem">
					<label>标题内容</label>
					<input autocomplete="off" maxlength="10" name="text" placeholder="请输入标题内容（10字以内）" value="${selectedText}"/>
				</div>`;
            let MtitleDialog = _this.createDialog({
                name:'centerTitle',
                title:'居中标题',
                width: 300,
                height:'auto',
                content:mTitleHtml,
                buttons:{
                    cancel: ['取消', function() {
                        this/*.hide()*/.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const title= MtitleDialog.find('input').val();
                        const str = `\n{mtitle title="${title}"/}\n\n`;
                        _this.replaceSelection(selection,selection.startColumn!==1 ? '\n'+str : str);
                        cm.focus()
                        this/*.hide()*/.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            })
        };
        //载入彩色虚线
        _this.handleDotted = function (){
            let cm = _this.Ed;
            let selection = cm.getSelection(); // 获取当前的选择区域

            const dottedHtml=`<div class="fitem">
					<label>开始颜色</label>
					<input style="width: 44px;padding: 0 2px;flex: none" autocomplete="off" value="#ff6c6c" name="startColor" type="color"/>
				</div>
				<div class="fitem">
					<label>结束颜色</label>
					<input style="width: 44px;padding: 0 2px;flex: none" autocomplete="off" value="#1989fa" name="endColor" type="color"/>
				</div>`;
            let dottedDialog = _this.createDialog({
                name:'dotted',
                title:'彩色虚线',
                width:380,
                height:'auto',
                content:dottedHtml,
                buttons:{
                    cancel:['取消',function (){
                        this/*.hide()*/.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const startColor = dottedDialog.find("input[name='startColor']").val();
                        const endColor = dottedDialog.find("input[name='endColor']").val();
                        const str = `\n{dotted startColor="${startColor}" endColor="${endColor}"/}\n\n`;
                        _this.replaceSelection(selection,selection.startColumn!==1 ? '\n'+str : str);
                        cm.focus()
                        this/*.hide()*/.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            })
        };
        //载入任务复选框
        _this.handleTask = function (type) {
            let cm = _this.Ed;
            let selection = cm.getSelection(); // 获取当前的选择区域
            const str = type ? '{x}' : '{ }';
            _this.replaceSelection(selection,` ${str}`);
            cm.focus();
        };
        //载入哔哩哔哩
        _this.handleBilibili = function (){
            let cm = _this.Ed;
            let selection = cm.getSelection(); // 获取当前的选择区域

            let biliHtml=`<div class="fitem">
					<label>视频Bvid</label>
					<input autocomplete="off" name="bvid" placeholder="请输入视频Bvid"/>
				</div>
				<div class="fitem">
					<label>视频选集</label>
					<input autocomplete="off" name="page" placeholder="请输入视频选集"/>
				</div>
                <div class="fitem">
					<label>视频宽度</label><input autocomplete="off" value="100%" name="width" placeholder="请输入宽度，默认100%"/>
                </div>
                <div class="fitem">
					<label>视频高度</label><input autocomplete="off" name="height" value="350px" placeholder="请输入高度，默认350px"/>
				</div>`;
            let biliDialog = _this.createDialog({
                name: 'bili',
                width: 380,
                height: 'auto',
                title: 'BiliBili视频',
                content: biliHtml,
                buttons: {
                    cancel: ['取消', function () {
                        this/*.hide()*/.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter: ['确定', function () {
                        const bvid = biliDialog.find('input[name="bvid"]').val();
                        const page = biliDialog.find('input[name="page"]').val() || 1;
                        let width = biliDialog.find('input[name="width"]').val() || '100%';
                        let height = biliDialog.find('input[name="height"]').val() || '350px';
                        if (!bvid) {
                            return _this.warningMsg('请输入Bvid');
                        }
                        if(width.indexOf('%')>-1){
                            width = width;
                        }else if(width.indexOf('px')>-1){
                            width = width;
                        }else if(typeof width === 'number'){
                            width = width+'px';
                        }else{
                            width = '100%';
                        }
                        if(height.indexOf('px')>-1){
                            height = height;
                        }else if(typeof height === 'number'){
                            height = height+'px';
                        }else{
                            height = '350px';
                        }
                        const str = `\n{bilibili bvid="${bvid}" page="${page}" width="${width}" height="${height}"/}\n\n`;
                        _this.replaceSelection(selection,(selection.startColumn !== 1) ? '\n' + str : str);
                        cm.focus()
                        this/*.hide()*/.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            });
        };
        //载入H1-H6
        _this.handleTitle = function (str){
            let cm = _this.Ed;
            let cur = cm.getPosition(); //获取当前光标位置
            let currentLineNumber = cur.lineNumber; //当前行号
            //选中当前行的内容
            const lineStart = new monaco.Position(currentLineNumber, 1);//实例化行开始位置
            const lineEnd = new monaco.Position(currentLineNumber, cm.getModel().getLineMaxColumn(currentLineNumber));//实例化行结束位置
            cm.setSelection(new monaco.Range(lineStart.lineNumber, lineStart.column, lineEnd.lineNumber, lineEnd.column)); //选中行内容


            let selection = cm.getSelection();//获取当前选择区域
            let lineTex   = _this.getSelectionText(selection)//cm.getModel().getLineContent(cur.lineNumber);//获取当前行内容,注释的方法也可以用



            if (cur.column !== 1) {
                let newPositionFirst = new monaco.Position(currentLineNumber, 1);//行首位置
                cm.setPosition(newPositionFirst);
                _this.replaceSelection(selection,`${str} ` + lineTex.replace(/#\s*/g,''));
                let newPositionLast = new monaco.Position(currentLineNumber, lineTex.length+str.length+2);//行尾的位置
                cm.setPosition(newPositionLast);
            } else {
                _this.replaceSelection(selection,`${str} `);
            }
            cm.focus();
        };
        //载入Link
        _this.handleLink = function (){
            let cm = _this.Ed;
            let selection = cm.getSelection(); // 获取当前的选择区域
            let selectionText = _this.getSelectionText(selection) || '';

            const linkHtml=`<div class="fitem">
                    <label>链接标题</label>
                    <input autocomplete="off" name="title" placeholder="请输入链接标题" value="${selectionText}"/>
                </div>
                <div class="fitem">
                    <label>链接地址</label>
                    <input autocomplete="off" name="url" placeholder="请输入链接地址"/>
                </div>`;
            let linkDialog = _this.createDialog({
                name: 'link',
                title: '插入链接',
                width: 380,
                height:'auto',
                content:linkHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const title = linkDialog.find("input[name='title']").val() || '';
                        const url = linkDialog.find("input[name='url']").val() || 'http://';
                        const str = `[${title}](${url})`;
                        _this.replaceSelection(selection,str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            })
        };
        //载入加粗
        _this.handleBold = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

            let cur = cm.getPosition(); //获取当前光标位置
            let currentLineNumber = cur.lineNumber; //当前行号

            _this.replaceSelection(selection,"**" + selectionText.replace(/\s/g,"") + "**");

            if(selectionText === "") {
                let newPositionLast = new monaco.Position(currentLineNumber, cur.column+2);//行尾的位置
                cm.setPosition(newPositionLast);
            }
            cm.focus();
        };
        //载入删除线
        _this.handleDel = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

            let cur = cm.getPosition(); //获取当前光标位置
            let currentLineNumber = cur.lineNumber; //当前行号

            _this.replaceSelection(selection,"~~" + selectionText.replace(/\s/g,"") + "~~");

            if(selectionText === "") {
                let newPositionLast = new monaco.Position(currentLineNumber, cur.column+2);//行尾的位置
                cm.setPosition(newPositionLast);
            }
            cm.focus();
        };
        //载入斜体
        _this.handleItalic = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

            let cur = cm.getPosition(); //获取当前光标位置
            let currentLineNumber = cur.lineNumber; //当前行号

            _this.replaceSelection(selection,"*" + selectionText.replace(/\s/g,"") + "*");

            if(selectionText === "") {
                let newPositionLast = new monaco.Position(currentLineNumber, cur.column+1);//行尾的位置
                cm.setPosition(newPositionLast);
            }
            cm.focus();
        };
        //载入引用
        _this.handleQuote = function (){
            let cm = _this.Ed;
            let cur = cm.getPosition(); //获取当前光标位置
            let currentLineNumber = cur.lineNumber; //当前行号
            //选中当前行的内容
            const lineStart = new monaco.Position(currentLineNumber, 1);//实例化行开始位置
            const lineEnd = new monaco.Position(currentLineNumber, cm.getModel().getLineMaxColumn(currentLineNumber));//实例化行结束位置
            cm.setSelection(new monaco.Range(lineStart.lineNumber, lineStart.column, lineEnd.lineNumber, lineEnd.column)); //选中行内容

            let selection = cm.getSelection();//获取当前选择区域
            let lineTex   = _this.getSelectionText(selection)//cm.getModel().getLineContent(cur.lineNumber);//获取当前行内容,注释的方法也可以用

            if (cur.column !== 1) {
                let newPositionFirst = new monaco.Position(currentLineNumber, 1);//行首位置
                cm.setPosition(newPositionFirst);
                _this.replaceSelection(selection,`> ` + lineTex.replace(/>\s*/g,''));
                let newPositionLast = new monaco.Position(currentLineNumber, lineTex.length+3);//行尾的位置
                cm.setPosition(newPositionLast);
            } else {
                _this.replaceSelection(selection,`> `);
            }
            cm.focus();
        };
        //载入无序列表
        _this.handleUnOrderedList = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

            if (selectionText === "") {
                _this.replaceSelection(selection,"- ");
            } else {
                let selectionArr = selectionText.split("\n");
                let listArr = [];
                for (let i = 0, len = selectionArr.length; i < len; i++) {
                    if(selectionArr[i].replace(/\s/g,'')){
                        listArr.push("- "+selectionArr[i].replace(/\s/g,''));
                    }
                }

                _this.replaceSelection(selection,listArr.join("\n"));
            }
            cm.focus();
        };
        //载入有序列表
        _this.handleOrderedList = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

            if (selectionText === "") {
                _this.replaceSelection(selection,"1. ");
            } else {
                let selectionArr = selectionText.split("\n");
                let listArr = [];
                let j=0;
                for (let i = 0, len = selectionArr.length; i < len; i++) {
                    if(selectionArr[i].replace(/\s/g,'')){
                        j++;
                        listArr.push(j+". "+selectionArr[i].replace(/\s/g,''));
                    }
                }

                _this.replaceSelection(selection,listArr.join("\n"));
            }
            cm.focus();
        };
        //载入Face
        _this.handleFace = function (){
            _this.initFace(function (){
                //2.加载表情包HTML
                let faceTabArr = Object.keys(_this.face.faceRes).map((item,index)=>{
                    return `<div class="tabbar-item ${index===0?'active':''}" data-show="${item}">${item}</div>`;
                });
                let faceListArr = Object.keys(_this.face.faceRes).map((item,index)=>{
                    let array=_this.face.faceRes[item].map(it=>{
                        if(item!=='颜文字') {
                            return `<div class="lists-item" data-text="${it.data}" title="${_this.getFaceTitle(it.data)}"><img src="${_this.pluginPath+it.icon}"></div> `;
                        }
                        return `<div class="lists-item" data-text="${it.data}">${it.icon}</div>`;
                    });
                    return `<div class="lists ${index===0?'active':''}" data-show="${item}">${array.join('')}</div>`;
                });
                let faceElem=`<div class="tabbar">${faceTabArr.join('')}</div>${faceListArr.join('')}`;
                //3.弹框
                let faceDialog = _this.createDialog({
                    name: 'face',
                    title: '图片表情',
                    width: 380,
                    height: 477,
                    content:faceElem
                });
                $('.face .tabbar>.tabbar-item').on('click',function(){
                    let showName=$(this).data('show');
                    $(this).addClass('active').siblings().removeClass('active');
                    $('body .face').find('.lists[data-show="'+showName+'"]').addClass('active').siblings().removeClass('active');
                })
                $('.face .lists>.lists-item').on('click',function (){
                    let text = $(this).data('text');
                    let cm        = _this.Ed;
                    let cursor = cm.getPosition();
                    let currentLineNumber = cursor.lineNumber; //当前行号
                    let currentColumn = cursor.column;//当前列号
                    let selection = cm.getSelection();//获取选中区域坐标位置
                    let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

                    if (cursor.column !== 1) {
                        _this.replaceSelection(selection,text);
                        let newPositionLast = new monaco.Position(currentLineNumber, currentColumn+text.length);//行尾的位置
                        cm.setPosition(newPositionLast);
                    } else {
                        _this.replaceSelection(selection,text);
                    }
                    faceDialog/*.hide()*/.lockScreen(false).hideMask();
                    cm.focus();
                })
            });
        };
        //载入符号表情
        _this.handleSymbol = function (){
            _this.initSymbol(function (res){
                if(res){
                    let thisTabArr = Object.keys(res).map((item,index)=>{
                        return `<div class="tabbar-item ${index===0?'active':''}" data-show="${item}">${item}</div>`;
                    });
                    let thisListArr = Object.keys(res).map((item,index)=>{
                        let array=res[item].split(' ').map(it=>{
                            return `<div class="lists-item" data-text="${it}">${it}</div>`;
                        });
                        return `<div class="lists ${index===0?'active':''}" data-show="${item}">${array.join('')}</div>`;
                    });
                    let thisElem=`<div class="tabbar">${thisTabArr.join('')}</div>${thisListArr.join('')}`;
                    let symbolDialog = _this.createDialog({
                        name: 'symbol',
                        title: '特殊符号',
                        width: 380,
                        height: 'auto',
                        content:thisElem
                    });
                    $('.symbol .tabbar>.tabbar-item').on('click',function(){
                        const activeTab = $(this);
                        const show = activeTab.attr('data-show');
                        const tabbar = $('.symbol .tabbar');
                        activeTab.addClass('active').siblings().removeClass('active');
                        tabbar.stop().animate({
                            scrollLeft: activeTab[0].offsetLeft - tabbar[0].offsetWidth / 2 + activeTab[0].offsetWidth / 2 - 15
                        });
                        $('.symbol .lists').removeClass('active');
                        $(".symbol .lists[data-show='" + show + "']").addClass('active');
                    })
                    $('.symbol .lists>.lists-item').on('click',function (){
                        let text = $(this).data('text');
                        let cm        = _this.Ed;
                        let cursor = cm.getPosition();
                        let currentLineNumber = cursor.lineNumber; //当前行号
                        let currentColumn = cursor.column;//当前列号
                        let selection = cm.getSelection();//获取选中区域坐标位置
                        let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

                        if (cursor.column !== 1) {
                            _this.replaceSelection(selection,text);
                            let newPositionLast = new monaco.Position(currentLineNumber, currentColumn+text.length);//行尾的位置
                            cm.setPosition(newPositionLast);
                        } else {
                            _this.replaceSelection(selection,text);
                        }
                        symbolDialog/*.hide()*/.lockScreen(false).hideMask();
                        cm.focus();
                    })
                }
            });
        };
        //载入特殊符号
        _this.handleSmile = function (){
            _this.initSmile(function (res){
                if(res){
                    let thisTabArr = Object.keys(res).map((item,index)=>{
                        return `<div class="tabbar-item ${index===0?'active':''}" data-show="${item}">${item}</div>`;
                    });
                    let thisListArr = Object.keys(res).map((item,index)=>{
                        let array=res[item].split(' ').map(it=>{
                            return `<div class="lists-item" data-text="${it}">${it}</div>`;
                        });
                        return `<div class="lists ${index===0?'active':''}" data-show="${item}">${array.join('')}</div>`;
                    });
                    let thisElem=`<div class="tabbar">${thisTabArr.join('')}</div>${thisListArr.join('')}`;
                    let smileDialog = _this.createDialog({
                        name: 'smile',
                        title: '符号表情（需数据库支持）',
                        width: 380,
                        height: 'auto',
                        content:thisElem
                    });
                    $('.smile .tabbar>.tabbar-item').on('click',function(){
                        const activeTab = $(this);
                        const show = activeTab.attr('data-show');
                        const tabbar = $('.smile .tabbar');
                        activeTab.addClass('active').siblings().removeClass('active');
                        tabbar.stop().animate({
                            scrollLeft: activeTab[0].offsetLeft - tabbar[0].offsetWidth / 2 + activeTab[0].offsetWidth / 2 - 15
                        });
                        $('.smile .lists').removeClass('active');
                        $(".smile .lists[data-show='" + show + "']").addClass('active');
                    })
                    $('.smile .lists>.lists-item').on('click',function (){
                        let text = $(this).data('text');
                        let cm        = _this.Ed;
                        let cursor = cm.getPosition();
                        let currentLineNumber = cursor.lineNumber; //当前行号
                        let currentColumn = cursor.column;//当前列号
                        let selection = cm.getSelection();//获取选中区域坐标位置
                        let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

                        if (cursor.column !== 1) {
                            _this.replaceSelection(selection,text);
                            let newPositionLast = new monaco.Position(currentLineNumber, currentColumn+text.length);//行尾的位置
                            cm.setPosition(newPositionLast);
                        } else {
                            _this.replaceSelection(selection,text);
                        }
                        smileDialog/*.hide()*/.lockScreen(false).hideMask();
                        cm.focus();
                    })
                }
            });
        };
        //载入缩进
        _this.handleIndent = function (){
            let cm = _this.Ed;
            let cur = cm.getPosition(); //获取当前光标位置
            let currentLineNumber = cur.lineNumber; //当前行号
            //选中当前行的内容
            const lineStart = new monaco.Position(currentLineNumber, 1);//实例化行开始位置
            const lineEnd = new monaco.Position(currentLineNumber, cm.getModel().getLineMaxColumn(currentLineNumber));//实例化行结束位置
            cm.setSelection(new monaco.Range(lineStart.lineNumber, lineStart.column, lineEnd.lineNumber, lineEnd.column)); //选中行内容

            let selection = cm.getSelection();//获取当前选择区域
            let lineTex   = _this.getSelectionText(selection)//cm.getModel().getLineContent(cur.lineNumber);//获取当前行内容,注释的方法也可以用

            if (cur.column !== 1) {
                let newPositionFirst = new monaco.Position(currentLineNumber, 1);//行首位置
                cm.setPosition(newPositionFirst);
                _this.replaceSelection(selection,`[~]` + lineTex.replace(/\[~\]/g,''));
                let newPositionLast = new monaco.Position(currentLineNumber, lineTex.length+4);//行尾的位置
                cm.setPosition(newPositionLast);
            } else {
                _this.replaceSelection(selection,`[~]`);
            }
            cm.focus();
        };
        //载入日期时间周
        _this.handleDatetime = function (){
            let cm = _this.Ed;
            let cur = cm.getPosition(); //获取当前光标位置
            let selection = cm.getSelection();//获取当前选择区域
            _this.handleTime(function (t){
                if(cur.column !== 1){
                    _this.replaceSelection(selection,"\n"+t);
                }else{
                    _this.replaceSelection(selection,t);
                }
                cm.focus();
            });
        };
        //载入HrLine
        _this.handleHrLine = function (){
            let cm = _this.Ed;
            let cur = cm.getPosition(); //获取当前光标位置
            let selection = cm.getSelection();//获取当前选择区域

            _this.replaceSelection(selection,((cur.column !== 1) ? "\n\n" : "\n") + "------------\n\n");
            cm.focus();
        };
        //载入下划线
        _this.handleUnderline = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

            let cur = cm.getPosition(); //获取当前光标位置
            let currentLineNumber = cur.lineNumber; //当前行号

            _this.replaceSelection(selection,"++" + selectionText.replace(/\s/g,"") + "++");

            if(selectionText === "") {
                let newPositionLast = new monaco.Position(currentLineNumber, cur.column+2);//行尾的位置
                cm.setPosition(newPositionLast);
            }
            cm.focus();
        };
        //载入表格
        _this.handleTable = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

            let cur = cm.getPosition(); //获取当前光标位置

            const tableHtml=`<div class="fitem">
                    <label>表格行</label>
                    <input style="width: 50px; flex: none; margin-right: 10px;" value="3" autocomplete="off" name="row"/>
                    <label>表格列</label>
                    <input style="width: 50px; flex: none;" value="3" autocomplete="off" name="column"/>
                </div>
                <div class="fitem">
                    <label>表格内容</label>
                    <label style="cursor: pointer"><input type="radio" name="align" value=":--"/> 居左</label> 
                    <label style="cursor: pointer"><input type="radio" name="align" value=":-:" checked/> 居中</label>
                    <label style="cursor: pointer"><input type="radio" name="align" value="--:"/> 居右</label>
                </div>`;
            let tableDialog=_this.createDialog({
                name: 'table',
                title:'插入表格',
                width: 380,
                height: 'auto',
                content: tableHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        let row = tableDialog.find("input[name='row']").val();
                        let column = tableDialog.find("input[name='column']").val();
                        let align = tableDialog.find("input[name='align']:checked").val();
                        if (isNaN(row)) row = 3;
                        if (isNaN(column)) column = 3;
                        let rowStr = '';
                        let rangeStr = '';
                        let columnlStr = '';
                        for (let i = 0; i < column; i++) {
                            rowStr += '| 表头 ';
                            rangeStr += '| '+align+' ';
                        }
                        for (let i = 0; i < row; i++) {
                            for (let j = 0; j < column; j++) columnlStr += '| 表格 ';
                            columnlStr += '|\n';
                        }
                        const htmlStr = `${rowStr}|\n${rangeStr}|\n${columnlStr}\n`;

                        _this.replaceSelection(selection,cur.column !== 1 ? '\n\n'+htmlStr : htmlStr);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            });
        };
        //载入代码块
        _this.handleCodeBlock = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

            let cur = cm.getPosition(); //获取当前光标位置

            const language = 'rss+atom+ssml+mathml+svg+html+markup+css+clike+js+javascript+abap+abnf+actionscript+ada+agda+al+antlr4+apacheconf+apex+apl+applescript+aql+arduino+arff+asciidoc+aspnet+asm6502+autohotkey+autoit+bash+basic+batch+bbcode+birb+bison+bnf+brainfuck+brightscript+bro+bsl+c+csharp+cpp+cfscript+chaiscript+cil+clojure+cmake+cobol+coffeescript+concurnas+csp+coq+crystal+css-extras+csv+cypher+d+dart+dataweave+dax+dhall+diff+django+dns-zone-file+docker+dot+ebnf+editorconfig+eiffel+ejs+elixir+elm+etlua+erb+erlang+excel-formula+fsharp+factor+false+firestore-security-rules+flow+fortran+ftl+gml+gcode+gdscript+gedcom+gherkin+git+glsl+go+graphql+groovy+haml+handlebars+haskell+haxe+hcl+hlsl+http+hpkp+hsts+ichigojam+icon+icu-message-format+idris+ignore+inform7+ini+io+j+java+javadoc+javadoclike+javastacktrace+jexl+jolie+jq+jsdoc+js-extras+json+json5+jsonp+jsstacktrace+js-templates+julia+keyman+kotlin+kumir+latex+latte+less+lilypond+liquid+lisp+livescript+llvm+log+lolcode+lua+makefile+markdown+markup-templating+matlab+mel+mizar+mongodb+monkey+moonscript+n1ql+n4js+nand2tetris-hdl+naniscript+nasm+neon+nevod+nginx+nim+nix+nsis+objectivec+ocaml+opencl+openqasm+oz+parigp+parser+pascal+pascaligo+psl+pcaxis+peoplecode+perl+php+phpdoc+php-extras+plsql+powerquery+powershell+processing+prolog+promql+properties+protobuf+pug+puppet+pure+purebasic+purescript+python+qsharp+q+qml+qore+r+racket+jsx+tsx+reason+regex+rego+renpy+rest+rip+roboconf+robotframework+ruby+rust+sas+sass+scss+scala+scheme+shell-session+smali+smalltalk+smarty+sml+solidity+solution-file+soy+sparql+splunk-spl+sqf+sql+squirrel+stan+iecst+stylus+swift+t4-templating+t4-cs+t4-vb+tap+tcl+tt2+textile+toml+turtle+twig+typescript+typoscript+unrealscript+uri+v+vala+vbnet+velocity+verilog+vhdl+vim+visual-basic+warpscript+wasm+wiki+xeora+xml+xojo+xquery+yaml+yang+zig';
            const languageArr = language.split('+').sort((a, b) => a.localeCompare(b));
            const sessionStorageType = sessionStorage.getItem('selectType') || 'js';
            let htmlStr = '';
            languageArr.forEach(item => {
                htmlStr += `<option ${sessionStorageType === item ? 'selected' : ''} value="${item}">${item.toUpperCase()}</option>`;
            });
            const codeBlockHtml=`<div class="fitem">
                    <label>语言类型</label>
                    <select name="type">
                        <option value="">- 请选择语言类型 -</option>
                        ${htmlStr}
                    </select>
                </div><div class="fitem">
                <div id="-fzy-code-block" style="width: 100%;height: 320px;"></div>
                </div>`;
            let codeEditor,blockCodeDialog = _this.createDialog({
                name:'codeBlock',
                title:'插入代码块',
                width:600,
                height:'auto',
                content:codeBlockHtml,
                success:function(dialog){
                    if(_this.cm){
                        codeEditor = _this.cm.create(document.getElementById('-fzy-code-block'),{
                            language:dialog.find("select[name='type']").val() || 'javascript',
                            automaticLayout: true,
                            scrollBeyondLastLine: !1,
                            tabSize: 2,
                            minimap: {
                                enabled: !1
                            },
                            overviewRulerBorder: false,
                            theme:_this.config.theme,
                            renderLineHighlightOnlyWhenFocus: !0,
                            wordWrap: "on",//换行
                            local:'zh-cn',//默认提示语言中文
                            fontSize:'16',
                        });
                        dialog.find("select[name='type']").on('change',function (){
                            let language = dialog.find("select[name='type']").val();
                            sessionStorage.setItem('selectType',language);
                            _this.cm.setModelLanguage(codeEditor.getModel(), language);
                        });
                    }
                },
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const type = blockCodeDialog.find("select[name='type']").val();
                        let str = codeEditor?codeEditor.getValue():'code here...';
                        if (!type) return _this.warningMsg('请选择需要输入的代码类型');
                        const htmlStr = `\`\`\`${type}\n${str}\n\`\`\``;
                        _this.replaceSelection(selection,cur.column !== 1 ? '\n\n'+htmlStr : htmlStr);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            });
        };
        //载入html5
        _this.handleHtml5 = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

            let cur = cm.getPosition(); //获取当前光标位置
            let htmlStr = `!!!\n htmlCode in here!如:<font color="red">我是红色</font>\n!!!\n`;
            _this.replaceSelection(selection,cur.column !== 1 ? '\n'+htmlStr : htmlStr);
            cm.focus();
        };
        //载入附件
        _this.handleFile = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

            let hasUrl = false;
            if(_this.isObject(_this.config.uploadFile)){
                if(_this.config.uploadFile.url){
                    hasUrl = true;
                }
            }
            if(typeof _this.config.uploadFile === 'function'){
                hasUrl = true;
            }

            const fileHtml=`<div class="fitem">
                    <label>附件标题</label>
                    <input autocomplete="off" name="title" placeholder="请输入附件标题" value="${selectionText}"/>
                </div>
                <div class="fitem">
                    <label>附件地址</label>
                    <input autocomplete="off" name="url" placeholder="请输入附件地址"/>
                    ${hasUrl?'<button type="button" upload>上传</button>':''}
                </div>`;
            let fileDialog = _this.createDialog({
                name: 'file',
                title: '插入附件',
                width: 380,
                height:'auto',
                content:fileHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const title = fileDialog.find("input[name='title']").val() || '';
                        if(!title){
                            return _this.errorMsg('请输入附件名称');
                        }
                        const url = fileDialog.find("input[name='url']").val() || 'http://';
                        const str = `[${title}](${url})`;
                        _this.replaceSelection(selection,str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            });
            //如果是自定义上传方法，则执行自定义方法
            if(typeof _this.config.uploadFile === 'function'){
                fileDialog.find('button[upload]').on('click', function(e) {
                    return _this.config.uploadFile(fileDialog);
                });
            }else{
                //如果不是则采用layui.upload 提供的方法
                let elem = fileDialog.find("button[upload]");
                if(!elem.length)return false;
                let obj = {
                    elem:elem[0],
                    done:function (res, index, upload){
                        let url='';
                        if(res.code===0){
                            if(typeof res.data === 'object'){
                                url=res.data.url;
                            }else if(typeof res.data === 'string'){
                                let result=JSON.parse(res.data);
                                url=result.url;
                            }
                            elem.prev().val(url);
                            return _this.successMsg(res.msg);
                        }
                        return _this.errorMsg(res.msg);
                    }
                }
                obj = $.extend({},obj,_this.config.uploadFile);
                _this.uploadFile(obj);
            }
        };
        //载入单图片
        _this.handleImage = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            let hasUrl = false;
            if(_this.isObject(_this.config.uploadImage)){
                if(_this.config.uploadImage.url){
                    hasUrl = true;
                }
            }
            if(typeof _this.config.uploadImage === 'function'){
                hasUrl = true;
            }
            const imgHtml=`<div class="fitem">
                    <label>图片标题</label>
                    <input autocomplete="off" name="title" placeholder="请输入图片标题" value="${selectionText}"/>
                </div>
                <div class="fitem">
                    <label>跳转地址</label>
                    <input autocomplete="off" name="jumpUrl" placeholder="请输入点击图片跳转地址，非必须" value=""/>
                </div>
                <div class="fitem">
                    <label>图片地址</label>
                    <input autocomplete="off" name="url" placeholder="请输入图片地址"/>
                    ${hasUrl?'<button type="button" upload>上传</button>':''}
                </div>`;
            let imgDialog = _this.createDialog({
                name: 'image',
                title: '插入图片',
                width: 380,
                height:'auto',
                content:imgHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const title = imgDialog.find("input[name='title']").val() || '';
                        if(!title)return _this.errorMsg('请输入附件名称');
                        const jumpUrl = imgDialog.find("input[name='jumpUrl']").val();
                        const url = imgDialog.find("input[name='url']").val();
                        if(!url)return _this.errorMsg('请输入图片地址');
                        let str='';
                        if(!jumpUrl){
                            str = `![${title}](${url})\n`;
                        }else{
                            str = `[![${title}](${url})](${jumpUrl})\n`;
                        }
                        _this.replaceSelection(selection,cur.column !== 1 ? '\n'+str : str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            });
            //如果是自定义上传方法，则执行自定义方法
            if(typeof _this.config.uploadImage === 'function'){
                imgDialog.find('button[upload]').on('click', function(e) {
                    return _this.config.uploadFile(imgDialog);
                });
            }else{
                //如果不是则采用layui.upload 提供的方法
                let elem = imgDialog.find("button[upload]");
                if(!elem.length)return false;
                let obj = {
                    elem:elem[0],
                    acceptMime:'image/*',
                    exts:'jpg|jpeg|png|gif|bmp|webp',
                    done:function (res, index, upload){
                        let url='';
                        if(res.code===0){
                            if(typeof res.data === 'object'){
                                url=res.data.url;
                            }else if(typeof res.data === 'string'){
                                let result=JSON.parse(res.data);
                                url=result.url;
                            }
                            elem.prev().val(url);
                            return _this.successMsg(res.msg);
                        }
                        return _this.errorMsg(res.msg);
                    }
                }
                obj = $.extend({},obj,_this.config.uploadImage);
                _this.uploadFile(obj);
            }
        };
        //载入多图片
        _this.handleImages = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置


            if(typeof _this.config.uploadImage === 'function'){
                return _this.config.uploadImage(true);//执行自定义方法
            }
            let hasUrl = false;
            if(_this.isObject(_this.config.uploadImage)){
                if(_this.config.uploadImage.url){
                    hasUrl = true;
                }
            }

            const imagesHtml=`<div class="-fzy-images">
                  <div class="-fzy-images-header"><span class="-fzy-images-tips">请选择文件进行上传</span><div class="-fzy-images-tool"><button type="button" selectImage>选择文件</button><button type="button" upload>开始上传</button></div></div>
                  <div class="-fzy-images-body">
                  <ul class="-fzy-images-list"><!--文件列表-->
                  </ul>
                  </div>
                  </div>`;
            let selectList=[];
            let imagesDialog = _this.createDialog({
                name:'images',
                title:'插入多图',
                width:860,
                height:550,
                content:imagesHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        if(selectList.length<1)return _this.errorMsg('请选择图片哦');
                        let str='';
                        for(let item of selectList){
                            str+= `![${item.filename}](${item.url})\n`;
                        }
                        _this.replaceSelection(selection,cur.column !== 1 ? '\n'+str : str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            });
            if(!hasUrl) return _this.errorMsg('未配置图片上传接口');
            let elem = imagesDialog.find('button[selectImage]')
                ,action = imagesDialog.find('button[upload]')
                ,listDom = imagesDialog.find('ul.-fzy-images-list')
                ,selectNum = 0
                ,successNum = 0
                ,uploadIns = undefined
            function uploadResult(){
                let msg=`请选择文件进行上传`;
                if(selectNum!==0 && successNum===0){
                    msg = `已选择${selectNum}个图片文件`;
                }else if(selectNum!==0 && successNum!==0){
                    msg = `已选择${selectNum}个图片文件，成功上传${successNum}个`;
                }
                imagesDialog.find('span.-fzy-images-tips').html(msg);
            }
            let obj={
                elem:elem[0],
                auto:false,
                bindAction:action[0],
                multiple:true,
                number:12,
                acceptMime:'image/*',
                exts:'jpg|jpeg|png|gif|bmp|webp',
                choose:function (obj){
                    var files = this.files = obj.pushFile(); //将每次选择的文件追加到文件队列
                    console.log(files);
                    obj.preview(function(index, file, result){
                        selectNum++;
                        let lis = $(['<li class="file-one" id="upload-' + index + '">'
                            , '<div class="file-check" title="点我删除"><span class="pi pi-times" style="color: indianred;"></span></div>'
                            , '<div class="file-view-one">'
                            , '<div class="file-success-upload layui-hide">上传成功</div>'
                            , '<img src="' + result + '">'
                            , '</div>'
                            , '<div class="file-title" title="' + file.name + '"><a href="javascript:;" class="file-title-a">' + file.name + '</a></div>'
                            , '</li>'].join(''));

                        listDom.append(lis);
                        uploadResult();
                        //删除
                        lis.find('.file-check').on('click',function () {
                            delete files[index];//删除对应文件
                            lis.remove();//移除该li块
                            uploadIns.config.elem.next()[0].value = ''; //清空 input file 值，以免删除后出现同名文件不可选
                            selectNum--;
                            uploadResult();
                        });
                        //重传
                        lis.find('.file-reupload').on('click', function(){
                            obj.upload(index, file);
                        })
                    });
                },
                done:function (res, index, upload){
                    if(res.code==0){ //上传成功
                        successNum++;
                        let data=undefined;
                        if(typeof res.data === 'object'){
                            data = res.data;
                        }else if(typeof res.data === 'string'){
                            data = JSON.parse(res.data);
                        }
                        var uli = listDom.find('li#upload-'+ index)
                            ,lis = uli.children();
                        uli.attr('data',res.data).bind('click',function (){
                            let that=this;
                            let data = JSON.parse($(that).attr('data'));
                            if($(that).hasClass('file-this')){
                                $(that).removeClass('file-this').children('div.file-check').removeClass('file-checked');
                                selectList = _this.removeElement(selectList,data);
                            }else {
                                $(that).addClass('file-this').children('div.file-check').addClass('file-checked');
                                $(that).find('div.file-success-upload').remove();
                                selectList.push(data);
                            }
                            // console.log(selectList);
                        });
                        lis.eq(0).attr('title','').html('<span class="pi pi-check"></span>').unbind('click');//移除click事件.html('<span class="fa fa-check"></span>').addClass('file-checked')
                        lis.eq(1).children('div.file-success-upload').removeClass('layui-hide');
                        lis.eq(2).attr('title',data.filename);
                        lis.eq(2).children('a.file-title-a').html(data.filename); //清空操作
                        uploadResult();
                        return delete this.files[index]; //删除文件队列已经上传成功的文件
                    }else {
                        _this.errorMsg(res.msg);
                        this.error(index, upload);
                    }
                },
                error: function(index, upload, res, xhr){
                    var uli = listDom.find('li#upload-'+ index)
                        ,lis = uli.children();
                    uli.addClass('file-error');
                    lis.eq(2).addClass('file-reupload');
                    lis.eq(2).children('a.file-title-a').html('<font color="#cd5c5c">重新上传</font>');
                }
            };
            obj = $.extend({},obj,_this.config.uploadImage);
            uploadIns = _this.uploadFile(obj);
        };
        //载入video/mp4/m3u8
        _this.handleVideo = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            var hasUrl = false;
            if(_this.isObject(_this.config.uploadVideo)){
                if(_this.config.uploadVideo.url){
                    hasUrl = true;
                }
            }
            if(typeof _this.config.uploadVideo == 'function'){
                hasUrl = true;
            }
            const videoHtml = `<div class="fitem">
					<label>视频地址</label>
					<input autocomplete="off" name="src" placeholder="请输入视频地址"/>
					${hasUrl?'<button type="button" upload>上传</button>':''}
				</div>
                <div class="fitem">
					<label>视频宽度</label><input autocomplete="off" value="100%" name="width" placeholder="请输入宽度，默认100%"/>
				</div>
				<div class="fitem">
					<label>视频高度</label><input autocomplete="off" name="height" value="350px" placeholder="请输入高度，默认350px"/>
				</div>`;
            let videoDialog = _this.createDialog({
                name: 'video',
                title: '插入视频',
                width: 380,
                height: 'auto',
                content:videoHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        if(!_this.config.player){
                            return _this.warningMsg('未配置播放器，设置 player:"能播放m3u8和MP4的播放器，可以参考DPlayer.min.js"');
                        }
                        const src=videoDialog.find('input[name="src"]').val();
                        let width = videoDialog.find('input[name="width"]').val() || '100%';
                        let height = videoDialog.find('input[name="height"]').val() || '350px';
                        if(width.indexOf('%')>-1){
                            width = width;
                        }else if(width.indexOf('px')>-1){
                            width = width;
                        }else if(typeof width === 'number'){
                            width = width+'px';
                        }else{
                            width = '100%';
                        }
                        if(height.indexOf('px')>-1){
                            height = height;
                        }else if(typeof height === 'number'){
                            height = height+'px';
                        }else{
                            height = '350px';
                        }
                        let str=`\n{dplayer src="${src}" width="${width}" height="${height}"/}\n\n`;
                        _this.replaceSelection(selection,cur.column !== 1 ? '\n'+str : str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            });
            if(typeof _this.config.uploadVideo == 'function'){
                videoDialog.find('button[upload]').bind('click',function (){
                    return _this.config.uploadVideo(videoDialog);
                });
            }else{
                let elem = videoDialog.find("button[upload]");
                if(!elem.length)return false;
                let obj = {
                    elem:elem[0],
                    acceptMime:'',
                    exts:'mp4|webm|ogg',
                    done:function (res, index, upload){
                        let url='';
                        if(res.code===0){
                            if(typeof res.data === 'object'){
                                url=res.data.url;
                            }else if(typeof res.data === 'string'){
                                let result=JSON.parse(res.data);
                                url=result.url;
                            }
                            elem.prev().val(url);
                            return _this.successMsg(res.msg);
                        }
                        return _this.errorMsg(res.msg);
                    }
                }
                obj = $.extend({},obj,_this.config.uploadVideo);
                _this.uploadFile(obj);
            }
        };
        //载入多彩按钮
        _this.getIconList = function (callback){
            $.get(COMMON_PATH+'css/font/icon.html',function (data){
                if(typeof callback === 'function'){
                    return callback(data);
                }
                return false;
            });
        };
        _this.handleABtn = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            _this.getIconList(function (data){
                const abtnHtml=`<div class="fitem">
					<label>按钮图标</label>
					<input autocomplete="off" name="icon" placeholder="请输入或选择图标"/>
				</div>
				<div class="icon-wrap flipInX">${data}</div>
				<div class="fitem">
					<label>图标大全</label>
					<span style="user-select: none;font-size:12px;color: lightseagreen">如果需要其他图标，自行引入图标库后手动填入</span>
				</div>
				<div class="fitem">
					<label>按钮颜色</label>
					<input style="width: 44px;padding: 0 2px;flex: none" autocomplete="off" value="#ff6800" name="color" type="color"/>
				</div>
				<div class="fitem">
					<label>跳转链接</label>
					<input autocomplete="off" name="href" placeholder="请输入跳转链接"/>
				</div>
				<div class="fitem">
					<label>按钮圆角</label>
					<input autocomplete="off" name="radius" placeholder="请输入按钮圆角，例：17.5px"/>
				</div>
				<div class="fitem">
					<label>按钮内容</label>
					<input autocomplete="off" name="content" placeholder="请输入按钮内容"/>
				</div>`;
                let abtnDialog = _this.createDialog({
                    name:'ABtn',
                    title:'多彩按钮',
                    width: 450,
                    height: 'auto',
                    content:abtnHtml,
                    buttons:{
                        cancel:['取消',function (){
                            this.lockScreen(false).hideMask();
                            return false;
                        }],
                        enter:['确定',function (){
                            const icon = abtnDialog.find("input[name='icon']").val();
                            const color = abtnDialog.find("input[name='color']").val();
                            const href = abtnDialog.find("input[name='href']").val();
                            const radius = abtnDialog.find("input[name='radius']").val();
                            const content = abtnDialog.find("input[name='content']").val();
                            const str = ` {abtn icon="${icon}" color="${color}" href="${href}" radius="${radius}" content="${content}"/} `;
                            _this.replaceSelection(selection,str);
                            cm.focus()
                            this.lockScreen(false).hideMask();
                            return false;
                        }]
                    }
                });
                abtnDialog.on('click','.icon-wrap>.-fzy-icon-item',function (){
                    let icon = $(this).children().children('span:first-child').attr('class');
                    abtnDialog.find("input[name='icon']").val(icon);
                });
            });



        };
        //载入便条按钮
        _this.handleANote = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            _this.getIconList(function (data){
                const aNoteHtml = `<div class="fitem">
					<label>按钮图标</label>
					<input autocomplete="off" name="icon" placeholder="请输入或选择图标"/>
				</div>
				<div class="icon-wrap flipInX">${data}</div>
				<div class="fitem">
					<label>图标大全</label>
					<span style="user-select: none;font-size:12px;color: lightseagreen">如果需要其他图标，自行引入图标库后手动填入</span>
				</div>
				<div class="fitem">
					<label>跳转链接</label>
					<input autocomplete="off" name="href" placeholder="请输入跳转链接"/>
				</div>
				<div class="fitem">
					<label>按钮类型</label>
					<select name="type">
						<option value="secondary" selected>secondary</option>
						<option value="success">success</option>
						<option value="warning">warning</option>
						<option value="error">error</option>
						<option value="info">info</option>
					</select>
				</div>
				<div class="fitem">
					<label>按钮内容</label>
					<input autocomplete="off" name="content" placeholder="请输入按钮内容"/>
				</div>`;
                let aNoteDialog = _this.createDialog({
                    name:'aNoteBtn',
                    title:'便条按钮',
                    width: 450,
                    height:'auto',
                    content:aNoteHtml,
                    buttons:{
                        cancel:['取消',function (){
                            this.lockScreen(false).hideMask();
                            return false;
                        }],
                        enter:['确定',function (){
                            const icon = aNoteDialog.find("input[name='icon']").val();
                            const href = aNoteDialog.find("input[name='href']").val();
                            const type = aNoteDialog.find("select[name='type']").val();
                            const content = aNoteDialog.find("input[name='content']").val();
                            const str = ` {anote icon="${icon}" href="${href}" type="${type}" content="${content}"/} `;
                            _this.replaceSelection(selection,str);
                            cm.focus()
                            this.lockScreen(false).hideMask();
                            return false;
                        }]
                    }
                });
                aNoteDialog.on('click','.icon-wrap>.-fzy-icon-item',function (){
                    let icon = $(this).children().children('span:first-child').attr('class');
                    aNoteDialog.find("input[name='icon']").val(icon);
                });
            });
        };
        //载入隐藏可见
        _this.handleHide = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            const str = `{hide}\n需要隐藏的内容\n{/hide}\n\n`;
            _this.replaceSelection(selection,cur.column !== 1 ? '\n\n'+str:'\n'+str);
            cm.focus()
        };
        //载入进度条
        _this.handleProgress = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            const progressHtml=`<div class="fitem">
					<label>百分比数</label>
					<input autocomplete="off" name="percentage" placeholder="请输入百分比（最大100%）"/>
				</div>
				<div class="fitem">
					<label>自定义色</label>
					<input style="width: 44px;padding: 0 2px;flex: none" autocomplete="off" value="#ff6c6c" name="color" type="color"/>
				</div>`;
            let progressDialog = _this.createDialog({
                name:'progressBar',
                title:'进度条',
                width:380,
                height:'auto',
                content:progressHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        let percentage = progressDialog.find("input[name='percentage']").val();
                        percentage = percentage.indexOf('%')>-1 ? percentage : percentage+'%';
                        const color = progressDialog.find("input[name='color']").val();
                        const str = `\n{progress percentage="${percentage}" color="${color}"/}\n\n`;
                        _this.replaceSelection(selection,cur.column !== 1?'\n'+str:str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            })
        };
        //载入跑马灯
        _this.handleLamp = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            const str = `{lamp/}\n\n`;
            _this.replaceSelection(selection,cur.column !== 1 ? '\n\n'+str:'\n'+str);
            cm.focus()
        };
        //载入卡片
        _this.handleCard = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            const cardHtml=`<div class="fitem">
					<label>卡片标题</label>
					<input autocomplete="off" name="label" placeholder="请输入卡片标题"/>
				</div>
				<div class="fitem">
					<label>卡片宽度</label>
					<input autocomplete="off" name="width" placeholder="请输入卡片宽度，例如：100%"/>
				</div>`;
            let cardDialog = _this.createDialog({
                name:'card',
                title:'默认卡片',
                width:380,
                height:'auto',
                content:cardHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const label = cardDialog.find("input[name='label']").val();
                        const width = cardDialog.find("input[name='width']").val();
                        const str = `\n{card-default label="${label}" width="${width}"}\n卡片内容\n{/card-default}\n\n`;
                        _this.replaceSelection(selection,cur.column !== 1 ? '\n'+str : str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            })
        };
        //载入tab
        _this.handleTabs = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            const str=`{tabs}\n{tabs-pane label="标签一"}\n 标签一内容\n{/tabs-pane}\n{tabs-pane label="标签二"}\n 标签二内容\n{/tabs-pane}\n{/tabs}\n\n`;
            _this.replaceSelection(selection,cur.column !== 1 ? '\n\n'+str : '\n'+str);
            cm.focus()
        };
        //载入卡片列表
        _this.handleCardList = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            const str=`{card-list}\n{card-list-item}\n 列表一内容\n{/card-list-item}\n{card-list-item}\n 列表二内容\n{/card-list-item}\n{/card-list}\n\n`;
            _this.replaceSelection(selection,cur.column !== 1 ? '\n\n'+str : '\n'+str);
            cm.focus()
        };
        //载入折叠卡片
        _this.handleAccordion = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置
            const str = `{collapse accordion=""}\n{collapse-item label="折叠标题一" open}\n 折叠内容一\n{/collapse-item}\n{collapse-item label="折叠标题二"}\n 折叠内容二\n{/collapse-item}\n{/collapse}\n\n`;
            _this.replaceSelection(selection,cur.column !== 1 ? '\n\n'+str : '\n'+str);
            cm.focus()
        };
        //载入标注卡片
        _this.handleCallout = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            const calloutHtml=`<div class="fitem">
					<label>边框颜色</label>
					<input style="width: 44px;padding: 0 2px;flex: none" autocomplete="off" value="#f0ad4e" name="color" type="color"/>
				</div>`;
            let calloutDialog = _this.createDialog({
                name:'callout',
                title:'插入标注',
                width:380,
                height:'auto',
                content:calloutHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const color = calloutDialog.find("input[name='color']").val();
                        const str = `\n{callout color="${color}"}\n${selectionText?selectionText:'标注内容'}\n{/callout}\n\n`;
                        _this.replaceSelection(selection,cur.column !== 1 ? '\n'+str : str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            })
        };
        //载入描述卡片
        _this.handleCardDescribe = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '卡片描述内容';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            const str = `{card-describe title="卡片描述"}\n${selectionText}\n{/card-describe}\n\n`;
            _this.replaceSelection(selection,cur.column !== 1 ? '\n\n'+str : '\n'+str);
            cm.focus()
        };
        //载入时间轴
        _this.handleTimeline = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            const str = `{timeline}\n{timeline-item color="#19be6b"}\n 正式上线\n{/timeline-item}\n{timeline-item color="#ed4014"}\n 删库跑路\n{/timeline-item}\n{/timeline}\n\n`;
            _this.replaceSelection(selection,cur.column !== 1 ? '\n\n'+str : '\n'+str);
            cm.focus()
        };
        //载入云盘下载
        _this.handleCloud = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            const cloudPanHtml = `<div class="fitem">
					<label>网盘类型</label>
					<select name="type">
						<option value="default" selected>默认网盘</option>
						<option value="360">360网盘</option>
						<option value="bd">百度网盘</option>
						<option value="al">阿里云盘</option>
						<option value="ty">天翼网盘</option>
						<option value="ct">城通网盘</option>
						<option value="wy">微云网盘</option>
						<option value="gitee">Gitee仓库</option>
						<option value="github">Github仓库</option>
						<option value="lz">蓝奏云网盘</option>
						<option value="123">123网盘</option>
						<option value="kk">夸克网盘</option>
					</select>
				</div>
				<div class="fitem">
					<label>显示标题</label>
					<input autocomplete="off" name="title" placeholder="请输入显示标题"/>
				</div>
				<div class="fitem">
					<label>下载地址</label>
					<input autocomplete="off" name="url" placeholder="请输入网盘地址"/>
				</div>
				<div class="fitem">
					<label>提取密码</label>
					<input autocomplete="off" name="password" placeholder="请输入提取码（非必填）"/>
				</div>`;
            let cloudDialog = _this.createDialog({
                name:'cloud',
                title:'网盘下载',
                width:380,
                height:'auto',
                content:cloudPanHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const type = cloudDialog.find("select[name='type']").val();
                        const title = cloudDialog.find("input[name='title']").val();
                        const url = cloudDialog.find("input[name='url']").val();
                        const password = cloudDialog.find("input[name='password']").val();
                        const str = `\n{cloud title="${title}" type="${type}" url="${url}" password="${password}"/}\n\n`;
                        _this.replaceSelection(selection,cur.column !== 1 ? '\n'+str : str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            });
        };
        //载入宫格
        _this.handleGird = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            const gridHtml = `<div class="fitem">
                    <label>宫格列数</label>
                    <input value="3" autocomplete="off" name="column" placeholder="请输入宫格列数"/>
                </div>
                <div class="fitem">
                    <label>宫格间隔</label>
                    <input value="15" autocomplete="off" name="gap" placeholder="请输入宫格间隔"/>
                </div>`;
            let gridDialog = _this.createDialog({
                name:'grid',
                title:'插入宫格',
                width:380,
                height:'auto',
                content:gridHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const column = gridDialog.find("input[name='column']").val() || 3;
                        const gap = gridDialog.find("input[name='gap']").val();
                        let lie=parseInt(column);
                        let itemStr = [];
                        for(let l=0;l<column;l++){
                            itemStr.push(`{gird-item}\n 宫格内容${l+1}\n{/gird-item}\n`);
                        }
                        const str = `{gird column="${column}" gap="${gap}"}\n${itemStr.join('')}{/gird}`;
                        _this.replaceSelection(selection,cur.column !== 1 ? '\n\n'+str : str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            })
        };
        //载入copy
        _this.handleCopy = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            const copyHtml=`<div class="fitem">
					<label>显示文案</label>
					<input autocomplete="off" name="showText" placeholder="请输入显示文案" value="${selectionText}"/>
				</div>
				<div class="fitem" style="align-items: flex-start">
					<label>复制内容</label>
					<textarea autocomplete="off" name="copyText" placeholder="请输入需要复制的内容"></textarea>
				</div>`;
            let copyDialog = _this.createDialog({
                name:'copy',
                title:'复制文本',
                width:380,
                height:'auto',
                content:copyHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const showText = copyDialog.find("input[name='showText']").val();
                        const copyText = copyDialog.find("textarea[name='copyText']").val();
                        const str = `\n{copy showText="${showText}" copyText="${copyText}"/}\n\n`;
                        _this.replaceSelection(selection,cur.column !== 1 ? '\n'+str : str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            })
        };
        //载入note消息
        _this.handleAlert = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            const alertHtml = `<div class="fitem">
					<label>提示类型</label>
					<select name="type">
						<option value="info" selected>info</option>
						<option value="success">success</option>
						<option value="warning">warning</option>
						<option value="error">error</option>
					</select>
				</div>`;
            let alertDialog = _this.createDialog({
                name:'alert',
                title:'警告提示',
                width:380,
                height:'auto',
                content:alertHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const type = alertDialog.find("select[name='type']").val();
                        const str = `\n{alert type="${type}"}\n${selectionText ? selectionText : '警告提示'}\n{/alert}\n\n`;
                        _this.replaceSelection(selection,cur.column !== 1 ? '\n'+str : str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            });
        };
        //载入audio
        _this.handleAudio = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            var hasUrl = false;
            if(_this.isObject(_this.config.uploadAudio)){
                if(_this.config.uploadAudio.url){
                    hasUrl = true;
                }
            }
            if(typeof _this.config.uploadAudio == 'function'){
                hasUrl = true;
            }

            var hasImgUrl = false;
            if(_this.isObject(_this.config.uploadImage)){
                if(_this.config.uploadImage.url){
                    hasImgUrl = true;
                }
            }
            if(typeof _this.config.uploadImage == 'function'){
                hasImgUrl = true;
            }

            const audioHtml = `<div class="fitem">
					<label>音频名称</label>
					<input autocomplete="off" name="name" placeholder="请输入音频名称"/>
				</div>
				<div class="fitem">
					<label>音频地址</label>
					<input autocomplete="off" name="url" placeholder="请输入音频地址"/>
					${hasUrl?'<button type="button" upload uploadaudio>上传</button>':''}
				</div>
				<div class="fitem">
					<label>音频封面</label>
					<input autocomplete="off" name="cover" placeholder="请输入图片地址"/>
					${hasImgUrl?'<button type="button" upload uploadimage>上传</button>':''}
				</div>
				<div class="fitem">
					<label>主题色彩</label>
					<input style="width: 44px;padding: 0 2px;flex: none" autocomplete="off" value="#f0ad4e" name="theme" type="color"/>
				</div>
				<div class="fitem">
					<label>自动播放</label>
					<select name="autoplay">
						<option value="1" selected>是</option>
						<option value="0">否</option>
					</select>
				</div>`;
            let audioDialog = _this.createDialog({
                name:'audio',
                title:'插入音频',
                width: 380,
                height: 'auto',
                content:audioHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const name = audioDialog.find("input[name='name']").val();
                        const url = audioDialog.find("input[name='url']").val();
                        const cover = audioDialog.find("input[name='cover']").val();
                        const theme = audioDialog.find("input[name='theme']").val();
                        const autoplay = audioDialog.find("select[name='autoplay']").val();
                        const str = `\n{mp3 name="${name}" url="${url}" cover="${cover}" theme="${theme}" ${autoplay === '1' ? 'autoplay="autoplay"' : ''}/}\n\n`;
                        _this.replaceSelection(selection,cur.column !== 1 ? '\n'+str : str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            });
            //上传音频
            if(typeof _this.config.uploadAudio === 'function'){
                audioDialog.find('button[uploadaudio]').bind('click',function (){
                    return _this.config.uploadAudio(audioDialog);
                });
            }else{
                let elem = audioDialog.find("button[uploadaudio]");
                if(elem.length) {
                    let obj = {
                        elem: elem[0],
                        acceptMime: '',
                        exts: 'mp3|m4a|wav|aac|ogg|midi|flac|amr|wma|webm',
                        done: function (res, index, upload) {
                            let url = '';
                            if (res.code === 0) {
                                if (typeof res.data === 'object') {
                                    url = res.data.url;
                                } else if (typeof res.data === 'string') {
                                    let result = JSON.parse(res.data);
                                    url = result.url;
                                }
                                elem.prev().val(url);
                                return _this.successMsg(res.msg);
                            }
                            return _this.errorMsg(res.msg);
                        }
                    }
                    obj = $.extend({}, obj, _this.config.uploadAudio);
                    _this.uploadFile(obj);
                }
            }
            //上传图片
            if(typeof _this.config.uploadImage === 'function'){
                audioDialog.find('button[uploadimage]').bind('click',function (){
                    return _this.config.uploadImage(audioDialog);
                });
            }else{
                let elem1 = audioDialog.find("button[uploadimage]");
                if(elem1.length) {
                    let obj = {
                        elem: elem1[0],
                        acceptMime: 'image/*',
                        exts: 'png|jpg|jpeg|gif|bmp|webp',
                        done: function (res, index, upload) {
                            let url = '';
                            if (res.code === 0) {
                                if (typeof res.data === 'object') {
                                    url = res.data.url;
                                } else if (typeof res.data === 'string') {
                                    let result = JSON.parse(res.data);
                                    url = result.url;
                                }
                                elem1.prev().val(url);
                                return _this.successMsg(res.msg);
                            }
                            return _this.errorMsg(res.msg);
                        }
                    }
                    obj = $.extend({}, obj, _this.config.uploadImage);
                    _this.uploadFile(obj);
                }
            }
        };
        //载入GOTOLINE
        _this.handleGoToLine = function (){
            let cm        = _this.Ed;
            let cur = cm.getPosition(); //获取当前光标位置
            let lineCount = cm.getModel().getLineCount();//cm.getValue().split('\n').length;

            const toLineHtml = `<div class="fitem">
                    <label>请输入行号1-${lineCount}</label>
                    <input autocomplete="off" name="line" type="number" placeholder="请输入行号" value="1"/>
                </div>`;
            let lineDialog = _this.createDialog({
                name:'gotoLine',
                title:'跳转到行',
                width:380,
                height:'auto',
                content:toLineHtml,
                buttons:{
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        const line = parseInt(lineDialog.find("input[name='line']").val() || 0);
                        if (line < 1 || line > lineCount) {
                            return _this.errorMsg(`请输入行号1-${lineCount}`);
                        }
                        cm.setPosition(new monaco.Position(line, 1));//光标跳转到行
                        cm.revealLineInCenter(line,'Smooth');
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            })
        };
        //载入banner轮播
        _this.handleBanner = function (){
            let cm        = _this.Ed;
            let selection = cm.getSelection();//获取选中区域坐标位置
            let selectionText = _this.getSelectionText(selection) || '';//获取选中文本
            let cur = cm.getPosition(); //获取当前光标位置

            let hasUrl = false;
            if(_this.isObject(_this.config.uploadImage)){
                if(_this.config.uploadImage.url){
                    hasUrl = true;
                }
            }
            if(typeof _this.config.uploadImage === 'function'){
                hasUrl = true;
            }
            const bannerHtml=`<div class="fitem">
                        <label>轮播宽度</label> <input autocomplete="off" name="width" type="text" placeholder="请输入宽度" value="100%"  style="margin-right: 40px"/>
                        <label>轮播高度</label> <input autocomplete="off" name="height" value="280px" type="text" placeholder="请输入高度"/>
                    </div>
                    <div class="fitem">
                        <label>动画类型</label>
                        <select name="anim" style="width: 100px;margin-right: 40px">
                            <option value="default" selected>左右切换</option>
                            <option value="updown">上下切换</option>
                            <option value="fade">渐隐渐显</option>
                        </select>
                        <label>箭头状态</label>
                        <select name="arrow">
                            <option value="hover" selected>悬停显示</option>
                            <option value="always">始终显示</option>
                            <option value="none">不显示</option>
                        </select>
                    </div>
                    <div class="fitem">
                        <label>手控位置</label>
                        <select name="indicator" style="margin-right: 40px">
                            <option value="inside" selected>内部</option>
                            <option value="outside">外部</option>
                            <option value="none">不显示</option>
                        </select>
                        <label>自动切换</label>
                        <select name="autoplay">
                            <option value="true" selected>自动滚动</option>
                            <option value="false">不自动滚动</option>
                            <option value="always">一直滚动</option>
                        </select>
                    </div>
                    <div class="fitem">
                        <label>间隔时间</label>
                        <input autocomplete="off" name="interval" value="3000" type="number" placeholder="请输入间隔时间，毫秒" style="margin-right: 40px"/>
                        <label>跳转方式</label>
                        <select name="target">
                            <option value="_self" selected>_self</option>
                            <option value="_blank">_blank</option>
                        </select>
                    </div>
                    <style>
                    #_bannerList label{white-space: nowrap;}
                    #_bannerList small{border-bottom: 1px dashed #eee;margin-bottom: 10px;width: 100%;display: block;margin-top: 10px;}
                    #_bannerList .fitem{padding-left: 10px;}
                    </style>
                    <div id="_bannerList">
                        <div class="_banner_item">
                        <small>组合1</small>
                        <div class="fitem">
                            <label>标题</label>
                            <input autocomplete="off" name="t[]" style="margin-right: 10px" placeholder="输入轮播标题"/>
                            <label>图片</label>
                            <input autocomplete="off" name="img[]" placeholder="输入轮播图片"/>
                            ${hasUrl?'<button type="button" upload>上传</button>':''}
                            <button type="button" class="layui-bg-red" remove>移除</button>
                        </div>
                        <div class="fitem">
                            <label>链接</label>
                            <input autocomplete="off" name="jumpUrl[]" placeholder="输入标题点击链接">
                        </div>
                        </div>
                    </div>`;
            let bannerDialog = _this.createDialog({
                name: 'banner',
                title: '插入图片轮播',
                width: 600,
                height: 'auto',
                content:bannerHtml,
                buttons:{
                    add:['+轮播选项',function (){
                        let num = this.find('small').length || 0;
                        num++;
                        const $item=$(`<div class="_banner_item">
                        <small>组合${num}</small>
                        <div class="fitem">
                            <label>标题</label>
                            <input autocomplete="off" name="t[]" style="margin-right: 10px" placeholder="输入轮播标题"/>
                            <label>图片</label>
                            <input autocomplete="off" name="img[]" placeholder="输入轮播图片"/>
                            ${hasUrl?'<button type="button" upload>上传</button>':''}
                            <button type="button" class="layui-bg-red" remove>移除</button>
                        </div>
                        <div class="fitem">
                            <label>链接</label>
                            <input autocomplete="off" name="jumpUrl[]" placeholder="输入标题点击链接">
                        </div>
                        </div>`).on('click','button[remove]',function (){
                            $(this).parents('._banner_item').remove();
                        });
                        this.find('div#_bannerList').append($item);
                        _upload_banner();
                    }],
                    cancel:['取消',function (){
                        this.lockScreen(false).hideMask();
                        return false;
                    }],
                    enter:['确定',function (){
                        let width = bannerDialog.find('input[name="width"]').val() || '100%';
                        let height = bannerDialog.find('input[name="height"]').val() || '280px';
                        const interval = bannerDialog.find('input[name="interval"]').val() || 3000;
                        const anim = bannerDialog.find('select[name="anim"]').val();
                        const arrow = bannerDialog.find('select[name="arrow"]').val();
                        const indicator = bannerDialog.find('select[name="indicator"]').val();
                        const target = bannerDialog.find('select[name="target"]').val();
                        let autoplay = bannerDialog.find('select[name="autoplay"]').val();
                        height = height.replace('px','')+'px';
                        width = width.indexOf('%')>-1 ? width : (width.replace('px','')+'px');
                        autoplay = autoplay==='always' ? autoplay : (autoplay==='true' ? true : false);
                        const t = bannerDialog.find('input[name="t[]"]').map(function(){
                            return this.value;
                        }).get();
                        const img = bannerDialog.find('input[name="img[]"]').map(function (){
                            return this.value;
                        }).get();
                        const jumpUrl = bannerDialog.find('input[name="jumpUrl[]"]').map(function (){
                            return this.value;
                        }).get();
                        // console.log(jumpUrl);
                        let str = `{banner width="${width}" height="${height}" interval="${interval}" anim="${anim}" arrow="${arrow}" indicator="${indicator}" autoplay="${autoplay}" target="${target}"}\n`;
                        for(let i in t){
                            str+=`{banner-item title="${t[i]}" image="${img[i]}" jumpUrl="${jumpUrl[i]}"/}\n`;
                        }
                        str+=`{/banner}\n`;
                        _this.replaceSelection(selection,cur.column !== 1 ? '\n'+str : str);
                        cm.focus()
                        this.lockScreen(false).hideMask();
                        return false;
                    }]
                }
            });
            bannerDialog.find('button[remove]').bind('click',function (){
                $(this).parents('._banner_item').remove();
            });
            _upload_banner();
            function _upload_banner(){
                if(typeof _this.config.uploadImage === 'function'){
                    bannerDialog.on('click','button[upload]', function(e) {
                        let that = this;
                        return _this.config.uploadImage($(that).prev());
                    });
                }else{
                    //如果不是则采用layui.upload 提供的方法
                    let elem = bannerDialog.find("button[upload]");
                    elem.each(function(index,item){
                        let obj = {
                            elem:elem[index],
                            acceptMime:'image/*',
                            exts:'jpg|jpeg|png|gif|bmp|webp|mp4',
                            done:function (res, index, upload){
                                let url='';
                                if(res.code===0){
                                    if(typeof res.data === 'object'){
                                        url=res.data.url;
                                    }else if(typeof res.data === 'string'){
                                        let result=JSON.parse(res.data);
                                        url=result.url;
                                    }
                                    $(item).prev().val(url);
                                    return _this.successMsg(res.msg);
                                }
                                return _this.errorMsg(res.msg);
                            }
                        }
                        obj = $.extend({},obj,_this.config.uploadImage);
                        _this.uploadFile(obj);
                    })
                }
            }
        };

        //获取cm的值
        _this.getValue = function(){
            return _this.Ed.getValue();
        };
        //获取解析后的html
        _this.getHtml = function(){
            const markdown = _this.Ed.getValue();
            let html = _this.createPreviewHtml(markdown);
            if(_this.config.autoParser && typeof _this.config.autoParser === 'function'){
                html = _this.config.autoParser(html);
            }
            return html;
        };
        //打开、关闭预览
        _this.preview = function (oThis){
            if(oThis) {
                if ($(oThis).hasClass('active')) {
                    $(oThis).removeClass('active'),
                    _this.config.preview = false,
                    _this.EL.editor.find('.-fzy-editor-view').css('width',''),
                    _this.EL.editor.find('.-fzy-editor-content').removeClass('viewed'),
                    _this.bindScrollEvent(false);
                } else {
                    $(oThis).addClass('active'),
                    _this.config.preview = true,
                    _this.EL.editor.find('.-fzy-editor-content').addClass('viewed'),
                    _this.bindScrollEvent(true);
                }
            }else{
                if ($('*[editor-event="preview"]').hasClass('active')) {
                    $('*[editor-event="preview"]').removeClass('active'),
                    _this.config.preview = false,
                    _this.EL.editor.find('.-fzy-editor-view').css('width',''),
                    _this.EL.editor.find('.-fzy-editor-content').removeClass('viewed'),
                    _this.bindScrollEvent(false);
                } else {
                    $('*[editor-event="preview"]').addClass('active'),
                    _this.config.preview = true,
                    _this.EL.editor.find('.-fzy-editor-content').addClass('viewed'),
                    _this.bindScrollEvent(true);
                }
            }
            _this.updatePreview();
        };
        //创建预览区域html
        _this.createPreviewHtml=function (str) {
            let player = _this.config.player || 'http://www.fengzhiya.cn/player/index.html?url='
            if (str.indexOf('[~]') !== -1) {
                str = str.replace(/\[~\]/g, '&nbsp;&nbsp;&nbsp;&nbsp;');
            }
            /* 生成html */
            str = Parser.makeHtml(str);
            str = str.replace(/\:\:\(\s*(呵呵|哈哈|吐舌|太开心|笑眼|花心|小乖|乖|捂嘴笑|滑稽|你懂的|不高兴|怒|汗|黑线|泪|真棒|喷|惊哭|阴险|鄙视|酷|啊|狂汗|what|疑问|酸爽|呀咩爹|委屈|惊讶|睡觉|笑尿|挖鼻|吐|犀利|小红脸|懒得理|勉强|爱心|心碎|玫瑰|礼物|彩虹|太阳|星星月亮|钱币|茶杯|蛋糕|大拇指|胜利|haha|OK|沙发|手纸|香蕉|便便|药丸|红领巾|蜡烛|音乐|灯泡|开心|钱|咦|呼|冷|生气|弱|吐血|狗头)\s*\)/g, function ($0, $1) {
                $1 = encodeURI($1).replace(/%/g, '');
                return `<img class="fzy-face" src="${_this.pluginPath}face/owo/paopao/${$1}_2x.png" />`;
            });
            str = str.replace(/\:\@\(\s*(高兴|小怒|脸红|内伤|装大款|赞一个|害羞|汗|吐血倒地|深思|不高兴|无语|亲亲|口水|尴尬|中指|想一想|哭泣|便便|献花|皱眉|傻笑|狂汗|吐|喷水|看不见|鼓掌|阴暗|长草|献黄瓜|邪恶|期待|得意|吐舌|喷血|无所谓|观察|暗地观察|肿包|中枪|大囧|呲牙|抠鼻|不说话|咽气|欢呼|锁眉|蜡烛|坐等|击掌|惊喜|喜极而泣|抽烟|不出所料|愤怒|无奈|黑线|投降|看热闹|扇耳光|小眼睛|中刀)\s*\)/g, function ($0, $1) {
                $1 = encodeURI($1).replace(/%/g, '');
                return `<img class="fzy-face" src="${_this.pluginPath}face/owo/aru/${$1}_2x.png" />`;
            });
            str = str.replace(/\:\$\(\s*(爱你|爱心|傲慢|白眼|棒棒糖|爆筋|抱拳|鄙视|闭嘴|擦汗|菜刀|吃|呲牙|大兵|大哭|蛋|得意|doge|发呆|发怒|奋斗|尴尬|勾引|鼓掌|害羞|憨笑|好棒|哈欠|喝彩|河蟹|坏笑|饥饿|惊恐|惊喜|惊讶|菊花|可爱|可怜|抠鼻|酷|快哭了|骷髅|困|篮球|泪奔|冷汗|流汗|流泪|难过|OK|喷血|撇嘴|啤酒|强|敲打|亲亲|糗大了|拳头|骚扰|色|胜利|手枪|衰|睡|调皮|偷笑|吐|托腮|委屈|微笑|握手|我最美|无奈|吓|小纠结|笑哭|小样儿|斜眼笑|西瓜|嘘|羊驼|阴险|疑问|右哼哼|幽灵|晕|再见|眨眼睛|折磨|咒骂|抓狂|左哼哼)\s*\)/g, function ($0, $1) {
                $1 = encodeURI($1).replace(/%/g, '');
                return `<img class="fzy-face" src="${_this.pluginPath}face/owo/QQ/${$1}.gif" />`;
            });
            if (str.indexOf('{lamp') !== -1) {
                str = str.replace(/{lamp\/}/g, '<span class="fzy_lamp"></span>');
            }
            if (str.indexOf('{x}') !== -1) {
                str = str.replace(/{x}/g, '<input type="checkbox" class="fzy_checkbox" disabled checked>');
            }
            if (str.indexOf('{ }') !== -1) {
                str = str.replace(/{ }/g, '<input type="checkbox" class="fzy_checkbox" disabled></input>');
            }
            if (str.indexOf('{mtitle') !== -1) {
                str = str.replace(/{mtitle([^}]*)\/}/g, '<fzy-mtitle $1></fzy-mtitle>');
            }
            if (str.indexOf('{dplayer') !== -1) {
                str = str.replace(/{dplayer([^}]*)\/}/g, '<fzy-dplayer player="' + player + '" $1 class="fzy_vplayer"></fzy-dplayer>');
            }
            if (str.indexOf('{bilibili') !== -1) {
                str = str.replace(/{bilibili([^}]*)\/}/g, '<fzy-bilibili $1 class="fzy_vplayer"></fzy-bilibili>');
            }
            if (str.indexOf('{music-list') !== -1) {
                str = str.replace(/{music-list([^}]*)\/}/g, '<fzy-mlist $1></fzy-mlist>');
            }
            if (str.indexOf('{music') !== -1) {
                str = str.replace(/{music([^}]*)\/}/g, '<fzy-music $1></fzy-music>');
            }
            if (str.indexOf('{mp3') !== -1) {
                str = str.replace(/{mp3([^}]*)\/}/g, '<fzy-mp3 $1></fzy-mp3>');
            }
            if (str.indexOf('{abtn') !== -1) {
                str = str.replace(/{abtn([^}]*)\/}/g, '<fzy-abtn $1></fzy-abtn>');
            }
            if (str.indexOf('{anote') !== -1) {
                str = str.replace(/{anote([^}]*)\/}/g, '<fzy-anote $1></fzy-anote>');
            }
            if (str.indexOf('{copy') !== -1) {
                str = str.replace(/{copy([^}]*)\/}/g, '<fzy-copy $1></fzy-copy>');
            }
            if (str.indexOf('{dotted') !== -1) {
                str = str.replace(/{dotted([^}]*)\/}/g, '<fzy-dotted $1></fzy-dotted>');
            }
            if (str.indexOf('{message') !== -1) {
                str = str.replace(/{message([^}]*)\/}/g, '<fzy-message $1></fzy-message>');
            }
            if (str.indexOf('{progress') !== -1) {
                str = str.replace(/{progress([^}]*)\/}/g, '<fzy-progress $1></fzy-progress>');
            }
            if (str.indexOf('{cloud') !== -1) {
                str = str.replace(/{cloud([^}]*)\/}/g, '<fzy-cloud $1></fzy-cloud>');
            }
            if (str.indexOf('{hide') !== -1) {
                str = str.replace(/{hide[^}]*}([\s\S]*?){\/hide}/g, '<fzy-hide></fzy-hide>');
            }
            if (str.indexOf('{card-default') !== -1) {
                str = str.replace(/{card-default([^}]*)}([\s\S]*?){\/card-default}/g, '<section style="margin-bottom: 15px"><fzy-card-default $1><span class="_temp" style="display: none">$2</span></fzy-card-default></section>');
            }
            if (str.indexOf('{banner')!==-1){
                str = str.replace(/{banner([^}]*)}([\s\S]*?){\/banner}/g,'<fzy-banner class="fzy_banner" $1><span class="_temp" style="display: none">$2</span></fzy-banner>');
            }
            if (str.indexOf('{callout') !== -1) {
                str = str.replace(/{callout([^}]*)}([\s\S]*?){\/callout}/g, '<section style="margin-bottom: 15px"><fzy-callout $1><span class="_temp" style="display: none">$2</span></fzy-callout></section>');
            }
            if (str.indexOf('{card-describe') !== -1) {
                str = str.replace(/{card-describe([^}]*)}([\s\S]*?){\/card-describe}/g, '<section style="margin-bottom: 15px"><fzy-card-describe $1><span class="_temp" style="display: none">$2</span></fzy-card-describe></section>');
            }
            if (str.indexOf('{tabs') !== -1) {
                str = str.replace(/{tabs}([\s\S]*?){\/tabs}/g, '<section style="margin-bottom: 15px"><fzy-tabs><span class="_temp" style="display: none">$1</span></fzy-tabs></section>');
            }
            if (str.indexOf('{card-list') !== -1) {
                str = str.replace(/{card-list}([\s\S]*?){\/card-list}/g, '<section style="margin-bottom: 15px"><fzy-card-list><span class="_temp" style="display: none">$1</span></fzy-card-list></section>');
            }
            if (str.indexOf('{timeline') !== -1) {
                str = str.replace(/{timeline}([\s\S]*?){\/timeline}/g, '<section style="margin-bottom: 15px"><fzy-timeline><span class="_temp" style="display: none">$1</span></fzy-timeline></section>');
            }
            if (str.indexOf('{collapse') !== -1) {
                str = str.replace(/{collapse accordion="([\s\S]*?)"}([\s\S]*?){\/collapse}/g, '<section style="margin-bottom: 15px"><fzy-collapse accordion="$1"><span class="_temp" style="display: none">$2</span></fzy-collapse></section>');
            }
            if (str.indexOf('{alert') !== -1) {
                str = str.replace(/{alert([^}]*)}([\s\S]*?){\/alert}/g, '<section style="margin-bottom: 15px"><fzy-alert $1><span class="_temp" style="display: none">$2</span></fzy-alert></section>');
            }
            if (str.indexOf('{gird') !== -1) {
                str = str.replace(/{gird([^}]*)}([\s\S]*?){\/gird}/g, '<section style="margin-bottom: 15px"><fzy-gird $1><span class="_temp" style="display: none">$2</span></fzy-gird></section>');
            }
            if (str.indexOf('[========]')!==-1){
                str = str.replace(/\[========\]/g,"<hr style=\"page-break-after:always;\" class=\"page-break fzy-page-break\" />");
            }
            if (/\+{2}(.+?)\+{2}/.test(str)){
                str = str.replace(/\+{2}(.+?)\+{2}/g,'<span style="text-decoration: underline;">\$1</span>');
            }
            return str;
        };

        //更新预览
        _this.updatePreview = function () {
            if(_this.config.preview) {
                const markdown = _this.Ed.getValue();
                if(!markdown){
                    return _this.EL.editor.find('.fzy-view').html('<div class="fzy-view-tip">预览区</div>');
                }
                let html = _this.createPreviewHtml(markdown);
                if(_this.config.autoParser && typeof _this.config.autoParser === 'function'){
                    html = _this.config.autoParser(html);
                }
                let formattedHtml = html.replace(/<pre><code class="language-(\w+)">/g, '<pre class="line-numbers"><code class="language-\$1">');
                _this.EL.editor.find('.fzy-view').html(formattedHtml);
                _this.EL.editor.find('.fzy-view p:empty').remove();
                // layui.form.render();
                Prism.highlightAll();
            }else{
                _this.EL.editor.find('.fzy-view').html('<div class="fzy-view-tip">预览区</div>');
            }
        };
        //绑定同步滚动预览
        _this.bindScrollEvent = function(flag) {
            if(!flag)return false;
            let cm = _this.Ed;
            cm.onDidScrollChange((M,A,P)=>{
                let cmScrollHeight = M.scrollHeight;//滚动总高度
                let cmScrollTop = M.scrollTop;//滚动的高度

                let e = document.querySelector('.-editor-write');
                let t=document.querySelector('.fzy-view');
                const n = cmScrollTop / (cmScrollHeight - e.offsetHeight);
                t.scrollTop = n * (t.scrollHeight - t.offsetHeight)
            });
            return _this;
        };
        //监听事件 编辑器内容改变事件
        _this.listenEvent = function (){
            if(_this.config.preview){
                _this.updatePreview();
            }
            //监听编辑器change事件
            _this.Ed.onDidChangeModelContent(function (){
                _this.updatePreview();
                if(_this.config.change && typeof _this.config.change === 'function'){
                    _this.config.change();
                }
            });
        };
        //一些公共方法
        _this.isObject = function (obj) {
            if (typeof obj === 'object' && obj !== null) {
                return Object.keys(obj).length !== 0;
            }
            return false; // 不是对象或为 null
        };
        //上传文件
        _this.uploadFile = function (obj){
            var _upload_setting={
                elem:undefined,
                url:undefined,
                field:'file',
                data:{},
                headers:{},
                dataType:'json',
                accept:'file',
                acceptMime:'*/*',
                exts:'jpg|jpeg|png|gif|webp|bmp|mp3|m4a|mp4|mpeg|avi|webm|mkv|zip|rar|7z|pdf|doc|docx|xls|xlsx|ppt|pptx|jar|php|exe|fzy|md',
                auto:true,
                bindAction:undefined,
                force:null,
                size:0,
                multiple:false,
                unified:false,
                number:0,
                drag:false
            }
            _upload_setting = $.extend({},_upload_setting,obj);
            if(!_upload_setting.elem){
                return _this.errorMsg('未配置选择器');
            }
            if(!_upload_setting.url){
                return _this.errorMsg('未配置上传接口');
            }
            if(_upload_setting.dataType!=='json'){
                return _this.errorMsg('返回接口必须是json配置');
            }
            // console.log(_upload_setting);
            return upload.render(_upload_setting);
        };
        //移除数组中的元素根据ID进行过滤
        _this.removeElement = function (arr, element,field='id') {
            return arr.filter(item => item[field] !== element[field]); // 过滤掉 id 匹配的元素
        };
        //设置工具栏事件
        _this.toolbarHandlers = {
            undo : function() {
                _this.Ed.trigger('','undo');
            },
            redo : function() {
                _this.Ed.trigger('','redo');
            },
            bold : function() {
                _this.handleBold();
            },
            del : function() {
                _this.handleDel();
            },
            italic : function() {
                _this.handleItalic();
            },
            underline : function (){
                _this.handleUnderline();
            },
            quote : function() {
                _this.handleQuote();
            },
            ucfirst : function() {
                let cm         = _this.Ed;
                let selection  = cm.getSelection();
                let selectionText = _this.getSelectionText(selection);

                _this.replaceSelection(selection,_this.firstUpperCase(selectionText));
                cm.focus();
            },
            ucwords : function() {
                let cm         = _this.Ed;
                let selection  = cm.getSelection();
                let selectionText = _this.getSelectionText(selection);

                _this.replaceSelection(_this.ucwords(selectionText));
                cm.focus();
            },
            uppercase : function() {
                let cm         = _this.Ed;
                let selection  = cm.getSelection();
                let selectionText = _this.getSelectionText(selection);


                _this.replaceSelection(selection,selectionText.toUpperCase());
                cm.focus();
            },
            lowercase : function() {
                let cm         = _this.Ed;
                let selection  = cm.getSelection();
                let selectionText = _this.getSelectionText(selection);


                _this.replaceSelection(selection,selectionText.toLowerCase());
                cm.focus();
            },
            h1 : function() {
                _this.handleTitle('#');
            },
            h2 : function() {
                _this.handleTitle('##');
            },
            h3 : function() {
                _this.handleTitle('###');
            },
            h4 : function() {
                _this.handleTitle('####');
            },
            h5 : function() {
                _this.handleTitle('#####');
            },
            h6 : function() {
                _this.handleTitle('######');
            },
            centerTitle : function (){
                _this.handleMTitle();
            },
            unorderedList : function() {
                _this.handleUnOrderedList();
            },
            orderedList : function() {
                _this.handleOrderedList();
            },
            tl:function (){
                _this.handleTask(false);
            },
            tlx:function (){
                _this.handleTask(true);
            },
            indent:function (){
                _this.handleIndent();
            },
            datetime:function (){
                _this.handleDatetime();
            },
            hr : function() {
                _this.handleHrLine();
            },
            dashedLine:function (){
                _this.handleDotted();
            },
            face:function (){
                _this.handleFace();
            },
            symbol:function (){
                _this.handleSymbol();
            },
            smile:function (){
                _this.handleSmile();
            },
            bili:function (){
                _this.handleBilibili();
            },
            link : function() {
                _this.handleLink();
            },
            pageBreak : function() {
                let cm        = _this.Ed;
                let selection = cm.getSelection();

                _this.replaceSelection(selection,"\r\n[========]\r\n");
            },
            img : function() {
                _this.handleImage();
            },
            images : function() {
                _this.handleImages();
            },
            file : function (){
                _this.handleFile();
            },
            video : function() {
                _this.handleVideo();
            },
            audio:function (){
                _this.handleAudio();
            },
            inlineCode : function() {
                let cm        = _this.Ed;
                let selection = cm.getSelection();//获取选中区域坐标位置
                let selectionText = _this.getSelectionText(selection) || '';//获取选中文本

                let cur = cm.getPosition(); //获取当前光标位置
                let currentLineNumber = cur.lineNumber; //当前行号

                _this.replaceSelection(selection,"`" + selectionText.replace(/\s/g,"") + "`");

                if(selectionText === "") {
                    let newPositionLast = new monaco.Position(currentLineNumber, cur.column+1);//行尾的位置
                    cm.setPosition(newPositionLast);
                }
                cm.focus();
            },
            codeBlock : function() {
                _this.handleCodeBlock();
            },
            html5 : function() {
                _this.handleHtml5();
            },
            table : function() {
                _this.handleTable();
            },
            btn:function (){
                _this.handleABtn();
            },
            noteBtn:function (){
                _this.handleANote();
            },
            hidden:function (){
                _this.handleHide();
            },
            progressBar:function (){
                _this.handleProgress();
            },
            marquee:function (){
                _this.handleLamp();
            },
            card:function (){
                _this.handleCard();
            },
            tabPage:function (){
                _this.handleTabs();
            },
            cardList:function (){
                _this.handleCardList();
            },
            foldCard:function (){
                _this.handleAccordion();
            },
            labelCard:function (){
                _this.handleCallout();
            },
            fieldCard:function (){
                _this.handleCardDescribe();
            },
            timeAxis:function (){
                _this.handleTimeline();
            },
            banner:function (){
                _this.handleBanner();
            },
            grid:function (){
                _this.handleGird();
            },
            copy:function (){
                _this.handleCopy();
            },
            note:function (){
                _this.handleAlert();
            },
            cloudPan:function (){
                _this.handleCloud();
            },
            gotoLine : function() {
                _this.handleGoToLine();
            },
            preview : function(oThis) {
                _this.preview(oThis);
            },
            fullscreen : function(oThis) {
                _this.fullscreen(oThis);
            },
            clear : function() {
                _this.clear();
            },
            search : function() {
                _this.Ed.trigger('editor', 'actions.find');
                _this.Ed.focus();
            },
            help : function() {
                const docsHref='https://md.fengzhiya.cn/';
                let keyArr = Object.keys(_this.keyMaps);
                let trH = [];
                for(let key of keyArr){
                    if(key){
                        let item = _this.keyMaps[key];
                        if(typeof item === 'string'){
                            trH.push(`<tr><td>${key}</td><td>${item}</td></tr>`);
                        }else if(typeof item === 'function'){
                            trH.push(`<tr><td>${key}</td><td>fn[内置方法，如果自定义替换将无法使用]</td></tr>`);
                        }
                    }
                }
                const helpHtml = `<p><b>fzyMD</b> 编辑器是一款可以网页引用的markdown编辑器，符合layui编写规则和引用.</p><br>
                    <blockquote class="layui-elem-quote layui-quote-nm">
                      快捷键，完全遵循monaco-Editor的规则
                    </blockquote>
                    <style>
                        .dark blockquote.layui-quote-nm{
                            border-color: #444;
                        }
                        .dark .layui-code-view{
                            border-color: #444;
                        }
                        .code-demo-1 .layui-code-wrap{
                            max-height:300px;
                        }
                        .dark .code-demo-1 .layui-code-wrap::-webkit-scrollbar,.dark .-fzy-editor-dialog-table::-webkit-scrollbar{
                            background: #333;
                        }
                        .dark .code-demo-1 .layui-code-wrap::-webkit-scrollbar-thumb,.dark .-fzy-editor-dialog-table::-webkit-scrollbar-thumb{
                            background: #444;
                        }
                        .dark .code-demo-1 .layui-code-wrap{
                            background-color: #333;
                            color: #fff;
                        }
                        .dark .code-demo-1 .layui-code-wrap .layui-code-line-content{
                            background-color: #222;
                        }
                        .-fzy-editor-dialog-table{
                            height:200px;
                            overflow-y:auto;
                            border:1px solid #444;
                            border-radis:4px;
                        }
                        .-fzy-editor-dialog-table .layui-table thead th{
                            position: sticky;
                            top: 0;
                            z-index:1;
                            background: #444;
                        }
                        .-fzy-editor-dialog-table .layui-table{
                            margin:0;
                        }
                        .-fzy-editor-dialog-table .layui-table th,.-fzy-editor-dialog-table .layui-table td{
                            border:none;
                        }
                        .dark .layui-table{
                            background-color:#333;
                            color: #e1e1e1;
                        }
                        .dark .layui-table th,.dark .layui-table td{
                            border-color:#444;
                        }
                    </style>
                    <b>fzyMD编辑器自定义快捷键如下设置</b>
                    <pre class="layui-code code-demo-1" lay-options="{}">
//配置里面的keyMap自定义快捷键
keyMap = {
    'Ctrl-1':h1, //如果是小键盘的数字，需要设置为N1
    // *如果是小键盘数字，未必能覆盖浏览器默认的数字快捷键*
    ...
}
                    </pre>
                    <br>
                    <b>fzyMD编辑器默认快捷键（默认快捷键可以被自定义快捷键覆盖·替换）</b>
                    <div class="-fzy-editor-dialog-table">
                    <table class="layui-table">
                        <thead>
                            <tr><th>键位</th><th>菜单/功能</th></tr>
                        <thead>
                        <tbody>
                            ${trH.join('')}
                        </tbody>
                    </table>
                    </div>
                `;
                _this.createDialog({
                    name:'help',
                    title:'帮助',
                    content:helpHtml,
                    width:600,
                    height:'auto',
                    success:function (){
                        layui.code({
                            elem:'.code-demo-1'
                        });
                    },
                    buttons:{
                        goto:['去官网',function (){
                            top.window.open(docsHref, '_blank');
                            this.lockScreen(false).hideMask();
                            return false;
                        }],
                        cancel:['关闭',function (){
                            this.lockScreen(false).hideMask();
                            return false;
                        }]
                    }
                })
            },
            about : function() {
                const aboutHtml=`<p><b>fzyMD</b> 编辑器是一款可以网页引用的markdown编辑器。</p>
                      <style>
                      .about p{text-indent: 2em;margin: 5px 0;}
                      .about a{color: #00A7AA;text-underline: #00A7AA;}
                      .about a:hover{color: indianred}
                      .about button{background: #00A7AA;color: #fff}
                      .about button:hover{opacity: .8}
                      </style>
                      <p>它是基于<a href="https://layui.dev/" target="_blank">Layui</a> 前端框架运转，内置了更多工具栏，可实时预览的强大编辑器。</p>
                      <p>可以自定义更多工具栏来丰富编辑器，内置了接口以供自定义，非常方便，基本上小白都能自定义。</p>
                      <p>
                      <fieldset class="layui-elem-field">
                        <legend style="font-size: 14px">引用插件</legend>
                         <div class="layui-field-box">
                            <ul>
                                <li>1.<a target="_blank" href="https://microsoft.github.io/monaco-editor/">manaco-editor - 直达</a></li>
                                <li>2.<a target="_blank" href="https://layui.dev/">Layui - 直达</a></li>
                                <li>3.<a target="_blank" href="https://aplayer.js.org/#/">APlayer.min.js - 直达</a></li>
                                <li>4.<a target="_blank" href="https://highlightjs.org/download">highlight.min.js - 直达</a></li>
                                <li>5.<a target="_blank" href="https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript">prism.js - 直达</a></li>
                                <li>6.<a target="_blank" href="https://marked.js.org/">marked.min.js - 直达</a></li>
                                <li>7.<a target="_blank" href="https://www.iconfont.cn/">阿里巴巴矢量图标库 - 直达</a></li>
                                <li>8.<a href="javascript:;">primeicons图标库</a></li>
                            </ul>
                         </div>
                      </fieldset>
                      </p><p>
                      <fieldset class="layui-elem-field">
                        <legend style="font-size: 14px">参考数据</legend>
                         <div class="layui-field-box">
                            <ul>
                                <li>1.<a target="_blank" href="https://pandao.github.io/editor.md/">editormd.min.js - 直达</a></li>
                                <li>2.<a href="javascript:;">Joe.editor - (不知道源码地址，它是基于HyperDown编写，借用它的解析库和表情库)</a></li>
                            </ul>
                         </div>
                      </fieldset>
                      </p>
                      <p style="text-indent: 0;color: red">*如果需要更多的图标库请自行页面引入，样式可以自行修改，本人对美感比较缺乏，请自行修改*</p>
                      <p style="text-indent: 0;"><h4>为什么要造fzyEditor？</h4>
                        <br>- 由于市面上很多的md编辑器在html中引用并不方便，也不便于扩展.
                        <br>- 又由于Layui本身并没有提供完善的编辑器，也方便在Layui中调用，Layui的三方扩展md编辑器也比较少且不完善.  
                        <br>- 市面上有的md编辑器在扩展上对很多开发者并不友好，我们希望每个开发者拿来即用.
                      </p>
                      <small>Copyright &copy; 2020 - ${new Date().getFullYear()} <a href="//www.fengzhiya.cn/">fengzhiya.cn</a>, The MIT License.</small>`;
                _this.createDialog({
                    name:'about',
                    title:'关于fzyEditor '+version,
                    content:aboutHtml,
                    width:600,
                    height:'auto',
                    buttons:{
                        cancel:['关闭',function (){
                            this.lockScreen(false).hideMask();
                            return false;
                        }]
                    }
                })
            }
        };
        //绑定工具栏事件
        _this.bindToolBarEvent = function (){
            _this.toolbarHandlers = $.extend({},_this.toolbarHandlers,_this.config.autoToolbarHandles);
            util.on('editor-event',_this.toolbarHandlers);
        };
        //绑定按键
        _this.bindKeyMapEvent = function (){
            //1.获取自定义的按键配置
            //2.绑定自带的按键配置，如有覆盖则按照自定义进行
            //3.开始绑定
            let cm              = _this.Ed;
            let settings        = _this.config;
            let toolbarHandlers = _this.toolbarHandlers;
            let disabledKeyMaps = settings.keyMap;
            let keyMaps = $.extend({},_this.keyMaps,disabledKeyMaps);
            let keyArr = Object.keys(keyMaps);
            let keyVS = {
                Ctrl:monaco.KeyMod.CtrlCmd,
                Alt:monaco.KeyMod.Alt,
                Shift:monaco.KeyMod.Shift,

                F1:monaco.KeyCode.F1,
                F2:monaco.KeyCode.F2,
                F3:monaco.KeyCode.F3,
                F4:monaco.KeyCode.F4,
                F5:monaco.KeyCode.F5,
                F6:monaco.KeyCode.F6,
                F7:monaco.KeyCode.F7,
                F8:monaco.KeyCode.F8,
                F9:monaco.KeyCode.F9,
                F10:monaco.KeyCode.F10,
                F11:monaco.KeyCode.F11,
                F12:monaco.KeyCode.F12,

                0:monaco.KeyCode.Digit0,
                1:monaco.KeyCode.Digit1,
                2:monaco.KeyCode.Digit2,
                3:monaco.KeyCode.Digit3,
                4:monaco.KeyCode.Digit4,
                5:monaco.KeyCode.Digit5,
                6:monaco.KeyCode.Digit6,
                7:monaco.KeyCode.Digit7,
                8:monaco.KeyCode.Digit8,
                9:monaco.KeyCode.Digit9,
                N0:monaco.KeyCode.Numpad0,
                N1:monaco.KeyCode.Numpad1,
                N2:monaco.KeyCode.Numpad2,
                N3:monaco.KeyCode.Numpad3,
                N4:monaco.KeyCode.Numpad4,
                N5:monaco.KeyCode.Numpad5,
                N6:monaco.KeyCode.Numpad6,
                N7:monaco.KeyCode.Numpad7,
                N8:monaco.KeyCode.Numpad8,
                N9:monaco.KeyCode.Numpad9,

                A:monaco.KeyCode.KeyA,
                B:monaco.KeyCode.KeyB,
                C:monaco.KeyCode.KeyC,
                D:monaco.KeyCode.KeyD,
                E:monaco.KeyCode.KeyE,
                F:monaco.KeyCode.KeyF,
                G:monaco.KeyCode.KeyG,
                H:monaco.KeyCode.KeyH,
                I:monaco.KeyCode.KeyI,
                J:monaco.KeyCode.KeyJ,
                K:monaco.KeyCode.KeyK,
                L:monaco.KeyCode.KeyL,
                M:monaco.KeyCode.KeyM,
                N:monaco.KeyCode.KeyN,
                O:monaco.KeyCode.KeyO,
                P:monaco.KeyCode.KeyP,
                Q:monaco.KeyCode.KeyQ,
                R:monaco.KeyCode.KeyR,
                S:monaco.KeyCode.KeyS,
                T:monaco.KeyCode.KeyT,
                U:monaco.KeyCode.KeyU,
                V:monaco.KeyCode.KeyV,
                W:monaco.KeyCode.KeyW,
                X:monaco.KeyCode.KeyX,
                Y:monaco.KeyCode.KeyY,
                Z:monaco.KeyCode.KeyZ,

                Enter:monaco.KeyCode.Enter,
            }

            function returnTitle(iKey='',iVal=''){
                if(iKey){
                    if(iKey === 'Shift-A'){return '@'}else if(iKey==='Enter'){return '回车'}else if(iKey==='Ctrl-D'){return '粘贴到下一行'}return '未知';
                }else if(iVal){
                    return $(tools[iVal]).attr('editor-title') || '未知';
                }
            }
            function returnKey(iKey){
                let kArr = iKey.split('-');
                if(kArr.length==1){
                    return [monaco.KeyMod.chord(keyVS[kArr[0]])];
                }else if(kArr.length==2){
                    return [monaco.KeyMod.chord(keyVS[kArr[0]] | keyVS[kArr[1]])];
                }else if(kArr.length==3){
                    return [monaco.KeyMod.chord(keyVS[kArr[0]] | keyVS[kArr[1]] | keyVS[kArr[2]])];
                }else if(kArr.length==4){
                    return [monaco.KeyMod.chord(keyVS[kArr[0]] | keyVS[kArr[1]] | keyVS[kArr[2]] | keyVS[kArr[3]])];
                }else if(kArr.length==5){
                    return [monaco.KeyMod.chord(keyVS[kArr[0]] | keyVS[kArr[1]] | keyVS[kArr[2]] | keyVS[kArr[3]] | keyVS[kArr[4]])];
                }
            }
            for(let i in keyArr){
                let ikey = keyArr[i];
                let iVal = keyMaps[ikey];
                let obj = {
                    id:ikey,
                    label:typeof iVal === 'string' ? returnTitle('',iVal) : returnTitle(ikey,''),
                    keybindings:returnKey(ikey),
                    run:function(...args){
                        if(typeof iVal === 'string'){
                            return toolbarHandlers[iVal]();
                        }
                        if(typeof iVal === 'function'){
                            return iVal(true);
                        }
                    }
                }
                // console.log(obj);
                cm.addAction(obj);
            }
            return _this;
        };
        //鼠标或触摸事件
        _this.mouseOrTouch = function(mouseEventType, touchEventType) {
            mouseEventType = mouseEventType || "click";
            touchEventType = touchEventType || "touchend";

            var eventType  = mouseEventType;

            try {
                document.createEvent("TouchEvent");
                eventType = touchEventType;
            } catch(e) {}

            return eventType;
        };
        //创建弹框
        _this.createDialog = function(options) {
            let defaults = {
                name : "",
                width : 420,
                height: 240,
                title : '',
                drag  : true,
                closed : true,
                content : '',
                mask : true,
                // maskStyle : {
                //     backgroundColor : "rgba(0,0,0,.5)",
                //     visibility:'visible'
                // },
                lockScreen : true,
                footer : true,
                buttons : false,
                success:undefined,
            };

            options          = $.extend(true, defaults, options);

            let $this        = _this;
            let editor       = $this.EL.editor;
            let classPrefix  = $this.classPrefix;
            let guid         = (new Date()).getTime();
            let dialogName   = ( (options.name === "") ? classPrefix + "dialog-" + guid : options.name);
            let editorMask   = editor.find("." + classPrefix + "mask");
            let mouseOrTouch = $this.mouseOrTouch;

            let html         = "<div class=\"" + classPrefix + "dialog " + dialogName +" "+"\">";

            if (options.title !== "")
            {
                html += "<div class=\"" + classPrefix + "dialog-header\"" + ( (options.drag) ? " style=\"cursor: move;\"" : "" ) + ">";
                html += "<strong class=\"" + classPrefix + "dialog-title\">" + options.title + "</strong>";
                html += "</div>";
            }

            if (options.closed)
            {
                html += "<a href=\"javascript:;\" class=\"pi pi-times " + classPrefix + "dialog-close\"></a>";
            }

            html += "<div class=\"" + classPrefix + "dialog-container\">" + options.content;

            if (options.footer || typeof options.footer === "string")
            {
                html += "<div class=\"" + classPrefix + "dialog-footer\">" + ( (typeof options.footer === "boolean") ? "" : options.footer) + "</div>";
            }

            html += "</div>";

            html += "<div class=\"" + classPrefix + "dialog-mask " + classPrefix + "dialog-mask-bg\"></div>";
            html += "<div class=\"" + classPrefix + "dialog-mask " + classPrefix + "dialog-mask-con\"></div>";
            html += "</div>";
            editorMask.html(html);

            let dialog = editorMask.find("." + dialogName);

            //载入成功后回调
            if(typeof options.success === 'function'){
                options.success(dialog);
            }

            setTimeout(()=>{
                editorMask.addClass('active')
            },100)

            dialog.lockScreen = function(lock) {
                if (options.lockScreen)
                {
                    $("html,body").css("overflow", (lock) ? "hidden" : "");
                }

                return dialog;
            };

            dialog.showMask = function() {
                if (options.mask)
                {
                    editorMask.addClass('active');
                }
                return dialog;
            };

            dialog.hideMask = function() {
                if (options.mask) {
                    editorMask.removeClass('active');
                    setTimeout(()=>{
                        editorMask.html('');
                    },150);
                }

                return dialog;
            };

            dialog.loading = function(show) {
                var loading = dialog.find("." + classPrefix + "dialog-mask");
                loading[(show) ? "show" : "hide"]();

                return dialog;
            };

            dialog.lockScreen(true);//.showMask();

            dialog/*.show()*/.css({
                zIndex : $this.dialogZindex,
                border : ($this.isIE8) ? "1px solid #ddd" : "",
                width  : (typeof options.width  === "number") ? options.width + "px"  : options.width,
                height : (typeof options.height === "number") ? options.height + "px" : options.height
            });
            editorMask.on('click',function (e){
                let mine = $("."+classPrefix + "dialog");
                let target = $(e.target);
                if (!mine.is(target) && mine.has(target).length === 0) {
                    dialog.lockScreen(false).hideMask();
                }
            })

            var dialogPosition = function(){
                dialog.css({
                    top    : ($(window).height() - dialog.height()) / 2 + "px",
                    left   : ($(window).width() - dialog.width()) / 2 + "px"
                });
            };

            dialogPosition();

            $(window).resize(dialogPosition);

            dialog.children("." + classPrefix + "dialog-close").bind(mouseOrTouch("click", "touchend"), function() {
                dialog.lockScreen(false).hideMask();
            });

            if (typeof options.buttons === "object")
            {
                var footer = dialog.footer = dialog.find("." + classPrefix + "dialog-footer");

                for (var key in options.buttons)
                {
                    var btn = options.buttons[key];
                    var btnClassName = classPrefix + key + "-btn";

                    footer.append("<button type='button' class=\"" + classPrefix + "btn " + btnClassName + "\">" + btn[0] + "</button>");
                    btn[1] = $.proxy(btn[1], dialog);
                    footer.children("." + btnClassName).bind(mouseOrTouch("click", "touchend"), btn[1]);
                }
            }

            if (options.title !== "" && options.drag)
            {
                var posX, posY;
                var dialogHeader = dialog.children("." + classPrefix + "dialog-header");

                if (!options.mask) {
                    dialogHeader.bind(mouseOrTouch("click", "touchend"), function(){
                        $this.dialogZindex += 2;
                        dialog.css("z-index", $this.dialogZindex);
                    });
                }

                dialogHeader.mousedown(function(e) {
                    e = e || window.event;  //IE
                    posX = e.clientX - parseInt(dialog[0].style.left);
                    posY = e.clientY - parseInt(dialog[0].style.top);

                    document.onmousemove = moveAction;
                });

                var userCanSelect = function (obj) {
                    obj.removeClass(classPrefix + "user-unselect").off("selectstart");
                };

                var userUnselect = function (obj) {
                    obj.addClass(classPrefix + "user-unselect").on("selectstart", function(event) { // selectstart for IE
                        return false;
                    });
                };

                var moveAction = function (e) {
                    e = e || window.event;  //IE

                    var left, top, nowLeft = parseInt(dialog[0].style.left), nowTop = parseInt(dialog[0].style.top);

                    if( nowLeft >= 0 ) {
                        if( nowLeft + dialog.width() <= $(window).width()) {
                            left = e.clientX - posX;
                        } else {
                            left = $(window).width() - dialog.width();
                            document.onmousemove = null;
                        }
                    } else {
                        left = 0;
                        document.onmousemove = null;
                    }

                    if( nowTop >= 0 ) {
                        top = e.clientY - posY;
                    } else {
                        top = 0;
                        document.onmousemove = null;
                    }


                    document.onselectstart = function() {
                        return false;
                    };

                    userUnselect($("body"));
                    userUnselect(dialog);
                    dialog[0].style.left = left + "px";
                    dialog[0].style.top  = top + "px";
                };

                document.onmouseup = function() {
                    userCanSelect($("body"));
                    userCanSelect(dialog);

                    document.onselectstart = null;
                    document.onmousemove = null;
                };

                dialogHeader.touchDraggable = function() {
                    var offset = null;
                    var start  = function(e) {
                        var orig = e.originalEvent;
                        var pos  = $(this).parent().position();

                        offset = {
                            x : orig.changedTouches[0].pageX - pos.left,
                            y : orig.changedTouches[0].pageY - pos.top
                        };
                    };

                    var move = function(e) {
                        e.preventDefault();
                        var orig = e.originalEvent;

                        $(this).parent().css({
                            top  : orig.changedTouches[0].pageY - offset.y,
                            left : orig.changedTouches[0].pageX - offset.x
                        });
                    };

                    this.bind("touchstart", start).bind("touchmove", move);
                };

                dialogHeader.touchDraggable();
            }

            $this.dialogZindex += 2;

            return dialog;
        };
        //清除编辑器内容
        _this.clear = function (){
            _this.Ed.setValue(''),_this.Ed.focus();
        };
        //全屏
        _this.fullscreen = function (oThis){
            let toolBarHeight = _this.EL.editor.find('.-fzy-tool').height();
            if(oThis){
                if($(oThis).hasClass('active')){
                    $(oThis).removeClass('active').attr('title','全屏').children('i').addClass('icon-quanping1').removeClass('icon-quanping');
                    _this.EL.editor.removeClass('fullScreen');
                    _this.EL.editor.find('.-editor-write').css('height',_this.config.height+'px');
                    _this.EL.editor.find('.-fzy-editor-view').css('height',_this.config.height+'px');
                    _this.EL.editor.find('.-fzy-editor-scope').css('height',_this.config.height+'px');
                }else {
                    $(oThis).addClass('active').attr('title','退出全屏').children('i').removeClass('icon-quanping1').addClass('icon-quanping');
                    _this.EL.editor.addClass('fullScreen')
                    _this.EL.editor.find('.-editor-write').css('height','calc(100vh - '+toolBarHeight+'px)');
                    _this.EL.editor.find('.-fzy-editor-view').css('height','calc(100vh - '+toolBarHeight+'px)');
                    _this.EL.editor.find('.-fzy-editor-scope').css('height','calc(100vh - '+toolBarHeight+'px)');
                }
            }else{
                if($('*[editor-event="fullscreen"]').hasClass('active') || _this.EL.editor.hasClass('fullScreen')){
                    $('*[editor-event="fullscreen"]').removeClass('active').attr('title','全屏').children('i').addClass('icon-quanping1').removeClass('icon-quanping');
                    _this.EL.editor.removeClass('fullScreen');
                    _this.EL.editor.find('.-editor-write').css('height',_this.config.height+'px');
                    _this.EL.editor.find('.-fzy-editor-view').css('height',_this.config.height+'px');
                    _this.EL.editor.find('.-fzy-editor-scope').css('height',_this.config.height+'px');
                }else{
                    $('*[editor-event="fullscreen"]').addClass('active').attr('title','退出全屏').children('i').removeClass('icon-quanping1').addClass('icon-quanping');
                    _this.EL.editor.addClass('fullScreen');
                    _this.EL.editor.find('.-editor-write').css('height','calc(100vh - '+toolBarHeight+'px)');
                    _this.EL.editor.find('.-fzy-editor-view').css('height','calc(100vh - '+toolBarHeight+'px)');
                    _this.EL.editor.find('.-fzy-editor-scope').css('height','calc(100vh - '+toolBarHeight+'px)');
                }
            }
        };
        //resize
        _this.resize = function (){
            $(window).resize(function () {
                if($('*[editor-event="fullscreen"]').hasClass('active') || _this.EL.editor.hasClass('fullScreen')) {
                    let toolBarHeight = _this.EL.editor.find('.-fzy-tool').height();
                    _this.EL.editor.find('.-editor-write').css('height', 'calc(100vh - ' + toolBarHeight + 'px)');
                    _this.EL.editor.find('.-fzy-editor-view').css('height','calc(100vh - '+toolBarHeight+'px)');
                    _this.EL.editor.find('.-fzy-editor-scope').css('height','calc(100vh - '+toolBarHeight+'px)');
                }
            });
        }
    }

    exports(MOD_NAME,{
        render(id,options){
            return new MD(id,options);
        }
    });
})